diff options
Diffstat (limited to 'arch')
1127 files changed, 16508 insertions, 38083 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 6ad00ad73459..640999412d11 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -700,6 +700,13 @@ config ARCH_MMAP_RND_COMPAT_BITS This value can be changed after boot using the /proc/sys/vm/mmap_rnd_compat_bits tunable +config HAVE_ARCH_COMPAT_MMAP_BASES + bool + help + This allows 64bit applications to invoke 32-bit mmap() syscall + and vice-versa 32-bit applications to call 64-bit mmap(). + Required for applications doing different bitness syscalls. + config HAVE_COPY_THREAD_TLS bool help diff --git a/arch/alpha/include/asm/extable.h b/arch/alpha/include/asm/extable.h new file mode 100644 index 000000000000..048e209e524c --- /dev/null +++ b/arch/alpha/include/asm/extable.h @@ -0,0 +1,55 @@ +#ifndef _ASM_EXTABLE_H +#define _ASM_EXTABLE_H + +/* + * 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_RELATIVE_EXTABLE + +#define swap_ex_entry_fixup(a, b, tmp, delta) \ + do { \ + (a)->fixup.unit = (b)->fixup.unit; \ + (b)->fixup.unit = (tmp).fixup.unit; \ + } while (0) + +#endif diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h index f939794363ac..fb01dfb760c2 100644 --- a/arch/alpha/include/asm/futex.h +++ b/arch/alpha/include/asm/futex.h @@ -19,12 +19,8 @@ "3: .subsection 2\n" \ "4: br 1b\n" \ " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .long 1b-.\n" \ - " lda $31,3b-1b(%1)\n" \ - " .long 2b-.\n" \ - " lda $31,3b-2b(%1)\n" \ - " .previous\n" \ + EXC(1b,3b,%1,$31) \ + EXC(2b,3b,%1,$31) \ : "=&r" (oldval), "=&r"(ret) \ : "r" (uaddr), "r"(oparg) \ : "memory") @@ -101,12 +97,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, "3: .subsection 2\n" "4: br 1b\n" " .previous\n" - " .section __ex_table,\"a\"\n" - " .long 1b-.\n" - " lda $31,3b-1b(%0)\n" - " .long 2b-.\n" - " lda $31,3b-2b(%0)\n" - " .previous\n" + EXC(1b,3b,%0,$31) + EXC(2b,3b,%0,$31) : "+r"(ret), "=&r"(prev), "=&r"(cmp) : "r"(uaddr), "r"((long)(int)oldval), "r"(newval) : "memory"); diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 94f587535dee..7b82dc9a8556 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h @@ -1,10 +1,6 @@ #ifndef __ALPHA_UACCESS_H #define __ALPHA_UACCESS_H -#include <linux/errno.h> -#include <linux/sched.h> - - /* * The fs value determines whether argument validity checking should be * performed or not. If get_fs() == USER_DS, checking is performed, with @@ -20,9 +16,6 @@ #define KERNEL_DS ((mm_segment_t) { 0UL }) #define USER_DS ((mm_segment_t) { -0x40000000000UL }) -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define get_fs() (current_thread_info()->addr_limit) #define get_ds() (KERNEL_DS) #define set_fs(x) (current_thread_info()->addr_limit = (x)) @@ -39,13 +32,13 @@ * - AND "addr+size" doesn't have any high-bits set * - OR we are in kernel mode. */ -#define __access_ok(addr, size, segment) \ - (((segment).seg & (addr | size | (addr+size))) == 0) +#define __access_ok(addr, size) \ + ((get_fs().seg & (addr | size | (addr+size))) == 0) -#define access_ok(type, addr, size) \ -({ \ - __chk_user_ptr(addr); \ - __access_ok(((unsigned long)(addr)), (size), get_fs()); \ +#define access_ok(type, addr, size) \ +({ \ + __chk_user_ptr(addr); \ + __access_ok(((unsigned long)(addr)), (size)); \ }) /* @@ -61,9 +54,9 @@ * (b) require any knowledge of processes at this stage */ #define put_user(x, ptr) \ - __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), get_fs()) + __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) #define get_user(x, ptr) \ - __get_user_check((x), (ptr), sizeof(*(ptr)), get_fs()) + __get_user_check((x), (ptr), sizeof(*(ptr))) /* * The "__xxx" versions do not do address space checking, useful when @@ -81,6 +74,11 @@ * more extensive comments with fixup_inline_exception below for * more information. */ +#define EXC(label,cont,res,err) \ + ".section __ex_table,\"a\"\n" \ + " .long "#label"-.\n" \ + " lda "#res","#cont"-"#label"("#err")\n" \ + ".previous\n" extern void __get_user_unknown(void); @@ -100,23 +98,23 @@ extern void __get_user_unknown(void); __gu_err; \ }) -#define __get_user_check(x, ptr, size, segment) \ -({ \ - long __gu_err = -EFAULT; \ - unsigned long __gu_val = 0; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - if (__access_ok((unsigned long)__gu_addr, size, segment)) { \ - __gu_err = 0; \ - switch (size) { \ - case 1: __get_user_8(__gu_addr); break; \ - case 2: __get_user_16(__gu_addr); break; \ - case 4: __get_user_32(__gu_addr); break; \ - case 8: __get_user_64(__gu_addr); break; \ - default: __get_user_unknown(); break; \ - } \ - } \ - (x) = (__force __typeof__(*(ptr))) __gu_val; \ - __gu_err; \ +#define __get_user_check(x, ptr, size) \ +({ \ + long __gu_err = -EFAULT; \ + unsigned long __gu_val = 0; \ + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + if (__access_ok((unsigned long)__gu_addr, size)) { \ + __gu_err = 0; \ + switch (size) { \ + case 1: __get_user_8(__gu_addr); break; \ + case 2: __get_user_16(__gu_addr); break; \ + case 4: __get_user_32(__gu_addr); break; \ + case 8: __get_user_64(__gu_addr); break; \ + default: __get_user_unknown(); break; \ + } \ + } \ + (x) = (__force __typeof__(*(ptr))) __gu_val; \ + __gu_err; \ }) struct __large_struct { unsigned long buf[100]; }; @@ -125,20 +123,14 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_64(addr) \ __asm__("1: ldq %0,%2\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0, 2b-1b(%1)\n" \ - ".previous" \ + EXC(1b,2b,%0,%1) \ : "=r"(__gu_val), "=r"(__gu_err) \ : "m"(__m(addr)), "1"(__gu_err)) #define __get_user_32(addr) \ __asm__("1: ldl %0,%2\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0, 2b-1b(%1)\n" \ - ".previous" \ + EXC(1b,2b,%0,%1) \ : "=r"(__gu_val), "=r"(__gu_err) \ : "m"(__m(addr)), "1"(__gu_err)) @@ -148,20 +140,14 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_16(addr) \ __asm__("1: ldwu %0,%2\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0, 2b-1b(%1)\n" \ - ".previous" \ + EXC(1b,2b,%0,%1) \ : "=r"(__gu_val), "=r"(__gu_err) \ : "m"(__m(addr)), "1"(__gu_err)) #define __get_user_8(addr) \ __asm__("1: ldbu %0,%2\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0, 2b-1b(%1)\n" \ - ".previous" \ + EXC(1b,2b,%0,%1) \ : "=r"(__gu_val), "=r"(__gu_err) \ : "m"(__m(addr)), "1"(__gu_err)) #else @@ -177,12 +163,8 @@ struct __large_struct { unsigned long buf[100]; }; " extwh %1,%3,%1\n" \ " or %0,%1,%0\n" \ "3:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0, 3b-1b(%2)\n" \ - " .long 2b - .\n" \ - " lda %0, 3b-2b(%2)\n" \ - ".previous" \ + EXC(1b,3b,%0,%2) \ + EXC(2b,3b,%0,%2) \ : "=&r"(__gu_val), "=&r"(__gu_tmp), "=r"(__gu_err) \ : "r"(addr), "2"(__gu_err)); \ } @@ -191,10 +173,7 @@ struct __large_struct { unsigned long buf[100]; }; __asm__("1: ldq_u %0,0(%2)\n" \ " extbl %0,%2,%0\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0, 2b-1b(%1)\n" \ - ".previous" \ + EXC(1b,2b,%0,%1) \ : "=&r"(__gu_val), "=r"(__gu_err) \ : "r"(addr), "1"(__gu_err)) #endif @@ -215,21 +194,21 @@ extern void __put_user_unknown(void); __pu_err; \ }) -#define __put_user_check(x, ptr, size, segment) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - if (__access_ok((unsigned long)__pu_addr, size, segment)) { \ - __pu_err = 0; \ - switch (size) { \ - case 1: __put_user_8(x, __pu_addr); break; \ - case 2: __put_user_16(x, __pu_addr); break; \ - case 4: __put_user_32(x, __pu_addr); break; \ - case 8: __put_user_64(x, __pu_addr); break; \ - default: __put_user_unknown(); break; \ - } \ - } \ - __pu_err; \ +#define __put_user_check(x, ptr, size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + if (__access_ok((unsigned long)__pu_addr, size)) { \ + __pu_err = 0; \ + switch (size) { \ + case 1: __put_user_8(x, __pu_addr); break; \ + case 2: __put_user_16(x, __pu_addr); break; \ + case 4: __put_user_32(x, __pu_addr); break; \ + case 8: __put_user_64(x, __pu_addr); break; \ + default: __put_user_unknown(); break; \ + } \ + } \ + __pu_err; \ }) /* @@ -240,20 +219,14 @@ extern void __put_user_unknown(void); #define __put_user_64(x, addr) \ __asm__ __volatile__("1: stq %r2,%1\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda $31,2b-1b(%0)\n" \ - ".previous" \ + EXC(1b,2b,$31,%0) \ : "=r"(__pu_err) \ : "m" (__m(addr)), "rJ" (x), "0"(__pu_err)) #define __put_user_32(x, addr) \ __asm__ __volatile__("1: stl %r2,%1\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda $31,2b-1b(%0)\n" \ - ".previous" \ + EXC(1b,2b,$31,%0) \ : "=r"(__pu_err) \ : "m"(__m(addr)), "rJ"(x), "0"(__pu_err)) @@ -263,20 +236,14 @@ __asm__ __volatile__("1: stl %r2,%1\n" \ #define __put_user_16(x, addr) \ __asm__ __volatile__("1: stw %r2,%1\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda $31,2b-1b(%0)\n" \ - ".previous" \ + EXC(1b,2b,$31,%0) \ : "=r"(__pu_err) \ : "m"(__m(addr)), "rJ"(x), "0"(__pu_err)) #define __put_user_8(x, addr) \ __asm__ __volatile__("1: stb %r2,%1\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda $31,2b-1b(%0)\n" \ - ".previous" \ + EXC(1b,2b,$31,%0) \ : "=r"(__pu_err) \ : "m"(__m(addr)), "rJ"(x), "0"(__pu_err)) #else @@ -298,16 +265,10 @@ __asm__ __volatile__("1: stb %r2,%1\n" \ "3: stq_u %2,1(%5)\n" \ "4: stq_u %1,0(%5)\n" \ "5:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda $31, 5b-1b(%0)\n" \ - " .long 2b - .\n" \ - " lda $31, 5b-2b(%0)\n" \ - " .long 3b - .\n" \ - " lda $31, 5b-3b(%0)\n" \ - " .long 4b - .\n" \ - " lda $31, 5b-4b(%0)\n" \ - ".previous" \ + EXC(1b,5b,$31,%0) \ + EXC(2b,5b,$31,%0) \ + EXC(3b,5b,$31,%0) \ + EXC(4b,5b,$31,%0) \ : "=r"(__pu_err), "=&r"(__pu_tmp1), \ "=&r"(__pu_tmp2), "=&r"(__pu_tmp3), \ "=&r"(__pu_tmp4) \ @@ -324,12 +285,8 @@ __asm__ __volatile__("1: stb %r2,%1\n" \ " or %1,%2,%1\n" \ "2: stq_u %1,0(%4)\n" \ "3:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda $31, 3b-1b(%0)\n" \ - " .long 2b - .\n" \ - " lda $31, 3b-2b(%0)\n" \ - ".previous" \ + EXC(1b,3b,$31,%0) \ + EXC(2b,3b,$31,%0) \ : "=r"(__pu_err), \ "=&r"(__pu_tmp1), "=&r"(__pu_tmp2) \ : "r"((unsigned long)(x)), "r"(addr), "0"(__pu_err)); \ @@ -341,153 +298,37 @@ __asm__ __volatile__("1: stb %r2,%1\n" \ * Complex access routines */ -/* This little bit of silliness is to get the GP loaded for a function - that ordinarily wouldn't. Otherwise we could have it done by the macro - directly, which can be optimized the linker. */ -#ifdef MODULE -#define __module_address(sym) "r"(sym), -#define __module_call(ra, arg, sym) "jsr $" #ra ",(%" #arg ")," #sym -#else -#define __module_address(sym) -#define __module_call(ra, arg, sym) "bsr $" #ra "," #sym " !samegp" -#endif - -extern void __copy_user(void); - -extern inline long -__copy_tofrom_user_nocheck(void *to, const void *from, long len) -{ - register void * __cu_to __asm__("$6") = to; - register const void * __cu_from __asm__("$7") = from; - register long __cu_len __asm__("$0") = len; - - __asm__ __volatile__( - __module_call(28, 3, __copy_user) - : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) - : __module_address(__copy_user) - "0" (__cu_len), "1" (__cu_from), "2" (__cu_to) - : "$1", "$2", "$3", "$4", "$5", "$28", "memory"); - - return __cu_len; -} - -#define __copy_to_user(to, from, n) \ -({ \ - __chk_user_ptr(to); \ - __copy_tofrom_user_nocheck((__force void *)(to), (from), (n)); \ -}) -#define __copy_from_user(to, from, n) \ -({ \ - __chk_user_ptr(from); \ - __copy_tofrom_user_nocheck((to), (__force void *)(from), (n)); \ -}) - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +extern long __copy_user(void *to, const void *from, long len); -extern inline long -copy_to_user(void __user *to, const void *from, long n) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long len) { - if (likely(__access_ok((unsigned long)to, n, get_fs()))) - n = __copy_tofrom_user_nocheck((__force void *)to, from, n); - return n; + return __copy_user(to, (__force const void *)from, len); } -extern inline long -copy_from_user(void *to, const void __user *from, long n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long len) { - long res = n; - if (likely(__access_ok((unsigned long)from, n, get_fs()))) - res = __copy_from_user_inatomic(to, from, n); - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; + return __copy_user((__force void *)to, from, len); } -extern void __do_clear_user(void); - -extern inline long -__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 long __clear_user(void __user *to, long len); extern inline long clear_user(void __user *to, long len) { - if (__access_ok((unsigned long)to, len, get_fs())) + if (__access_ok((unsigned long)to, len)) 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) + (uaccess_kernel() ? ~0UL : TASK_SIZE) 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_RELATIVE_EXTABLE - -#define swap_ex_entry_fixup(a, b, tmp, delta) \ - do { \ - (a)->fixup.unit = (b)->fixup.unit; \ - (b)->fixup.unit = (tmp).fixup.unit; \ - } while (0) - +#include <asm/extable.h> #endif /* __ALPHA_UACCESS_H */ diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index afc901b7a6f6..148d7a32754e 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -99,4 +99,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0b961093ca5c..9ec56dc97374 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1016,6 +1016,7 @@ SYSCALL_DEFINE2(osf_gettimeofday, struct timeval32 __user *, tv, SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv, struct timezone __user *, tz) { + struct timespec64 kts64; struct timespec kts; struct timezone ktz; @@ -1023,13 +1024,14 @@ SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv, if (get_tv32((struct timeval *)&kts, tv)) return -EFAULT; kts.tv_nsec *= 1000; + kts64 = timespec_to_timespec64(kts); } if (tz) { if (copy_from_user(&ktz, tz, sizeof(*tz))) return -EFAULT; } - return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); + return do_sys_settimeofday64(tv ? &kts64 : NULL, tz ? &ktz : NULL); } asmlinkage long sys_ni_posix_timers(void); @@ -1290,7 +1292,7 @@ SYSCALL_DEFINE1(old_adjtimex, struct timex32 __user *, txc_p) /* copy relevant bits of struct timex. */ if (copy_from_user(&txc, txc_p, offsetof(struct timex32, time)) || copy_from_user(&txc.tick, &txc_p->tick, sizeof(struct timex32) - - offsetof(struct timex32, time))) + offsetof(struct timex32, tick))) return -EFAULT; ret = do_adjtimex(&txc); diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index b137390e87e7..65bb102d985b 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -482,12 +482,8 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, " extwl %1,%3,%1\n" " extwh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -502,12 +498,8 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, " extll %1,%3,%1\n" " extlh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -522,12 +514,8 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, " extql %1,%3,%1\n" " extqh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -551,16 +539,10 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, "3: stq_u %2,1(%5)\n" "4: stq_u %1,0(%5)\n" "5:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %2,5b-1b(%0)\n" - " .long 2b - .\n" - " lda %1,5b-2b(%0)\n" - " .long 3b - .\n" - " lda $31,5b-3b(%0)\n" - " .long 4b - .\n" - " lda $31,5b-4b(%0)\n" - ".previous" + EXC(1b,5b,%2,%0) + EXC(2b,5b,%1,%0) + EXC(3b,5b,$31,%0) + EXC(4b,5b,$31,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) : "r"(va), "r"(una_reg(reg)), "0"(0)); @@ -581,16 +563,10 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, "3: stq_u %2,3(%5)\n" "4: stq_u %1,0(%5)\n" "5:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %2,5b-1b(%0)\n" - " .long 2b - .\n" - " lda %1,5b-2b(%0)\n" - " .long 3b - .\n" - " lda $31,5b-3b(%0)\n" - " .long 4b - .\n" - " lda $31,5b-4b(%0)\n" - ".previous" + EXC(1b,5b,%2,%0) + EXC(2b,5b,%1,%0) + EXC(3b,5b,$31,%0) + EXC(4b,5b,$31,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) : "r"(va), "r"(una_reg(reg)), "0"(0)); @@ -611,16 +587,10 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, "3: stq_u %2,7(%5)\n" "4: stq_u %1,0(%5)\n" "5:\n" - ".section __ex_table,\"a\"\n\t" - " .long 1b - .\n" - " lda %2,5b-1b(%0)\n" - " .long 2b - .\n" - " lda %1,5b-2b(%0)\n" - " .long 3b - .\n" - " lda $31,5b-3b(%0)\n" - " .long 4b - .\n" - " lda $31,5b-4b(%0)\n" - ".previous" + EXC(1b,5b,%2,%0) + EXC(2b,5b,%1,%0) + EXC(3b,5b,$31,%0) + EXC(4b,5b,$31,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) : "r"(va), "r"(una_reg(reg)), "0"(0)); @@ -802,7 +772,7 @@ do_entUnaUser(void __user * va, unsigned long opcode, /* Don't bother reading ds in the access check since we already know that this came from the user. Also rely on the fact that the page at TASK_SIZE is unmapped and so can't be touched anyway. */ - if (!__access_ok((unsigned long)va, 0, USER_DS)) + if ((unsigned long)va >= TASK_SIZE) goto give_sigsegv; ++unaligned[1].count; @@ -835,12 +805,8 @@ do_entUnaUser(void __user * va, unsigned long opcode, " extwl %1,%3,%1\n" " extwh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -855,12 +821,8 @@ do_entUnaUser(void __user * va, unsigned long opcode, " extll %1,%3,%1\n" " extlh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -875,12 +837,8 @@ do_entUnaUser(void __user * va, unsigned long opcode, " extql %1,%3,%1\n" " extqh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -895,12 +853,8 @@ do_entUnaUser(void __user * va, unsigned long opcode, " extll %1,%3,%1\n" " extlh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -915,12 +869,8 @@ do_entUnaUser(void __user * va, unsigned long opcode, " extql %1,%3,%1\n" " extqh %2,%3,%2\n" "3:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %1,3b-1b(%0)\n" - " .long 2b - .\n" - " lda %2,3b-2b(%0)\n" - ".previous" + EXC(1b,3b,%1,%0) + EXC(2b,3b,%2,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) : "r"(va), "0"(0)); if (error) @@ -944,16 +894,10 @@ do_entUnaUser(void __user * va, unsigned long opcode, "3: stq_u %2,1(%5)\n" "4: stq_u %1,0(%5)\n" "5:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %2,5b-1b(%0)\n" - " .long 2b - .\n" - " lda %1,5b-2b(%0)\n" - " .long 3b - .\n" - " lda $31,5b-3b(%0)\n" - " .long 4b - .\n" - " lda $31,5b-4b(%0)\n" - ".previous" + EXC(1b,5b,%2,%0) + EXC(2b,5b,%1,%0) + EXC(3b,5b,$31,%0) + EXC(4b,5b,$31,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) : "r"(va), "r"(*reg_addr), "0"(0)); @@ -978,16 +922,10 @@ do_entUnaUser(void __user * va, unsigned long opcode, "3: stq_u %2,3(%5)\n" "4: stq_u %1,0(%5)\n" "5:\n" - ".section __ex_table,\"a\"\n" - " .long 1b - .\n" - " lda %2,5b-1b(%0)\n" - " .long 2b - .\n" - " lda %1,5b-2b(%0)\n" - " .long 3b - .\n" - " lda $31,5b-3b(%0)\n" - " .long 4b - .\n" - " lda $31,5b-4b(%0)\n" - ".previous" + EXC(1b,5b,%2,%0) + EXC(2b,5b,%1,%0) + EXC(3b,5b,$31,%0) + EXC(4b,5b,$31,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) : "r"(va), "r"(*reg_addr), "0"(0)); @@ -1012,16 +950,10 @@ do_entUnaUser(void __user * va, unsigned long opcode, "3: stq_u %2,7(%5)\n" "4: stq_u %1,0(%5)\n" "5:\n" - ".section __ex_table,\"a\"\n\t" - " .long 1b - .\n" - " lda %2,5b-1b(%0)\n" - " .long 2b - .\n" - " lda %1,5b-2b(%0)\n" - " .long 3b - .\n" - " lda $31,5b-3b(%0)\n" - " .long 4b - .\n" - " lda $31,5b-4b(%0)\n" - ".previous" + EXC(1b,5b,%2,%0) + EXC(2b,5b,%1,%0) + EXC(3b,5b,$31,%0) + EXC(4b,5b,$31,%0) : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) : "r"(va), "r"(*reg_addr), "0"(0)); @@ -1047,7 +979,7 @@ give_sigsegv: /* We need to replicate some of the logic in mm/fault.c, since we don't have access to the fault code in the exception handling return path. */ - if (!__access_ok((unsigned long)va, 0, USER_DS)) + if ((unsigned long)va >= TASK_SIZE) info.si_code = SEGV_ACCERR; else { struct mm_struct *mm = current->mm; diff --git a/arch/alpha/lib/clear_user.S b/arch/alpha/lib/clear_user.S index bf5b931866ba..006f469fef73 100644 --- a/arch/alpha/lib/clear_user.S +++ b/arch/alpha/lib/clear_user.S @@ -8,21 +8,6 @@ * right "bytes left to zero" value (and that it is updated only _after_ * a successful copy). There is also some rather minor exception setup * stuff. - * - * NOTE! This is not directly C-callable, because the calling semantics - * are different: - * - * Inputs: - * length in $0 - * destination address in $6 - * exception pointer in $7 - * return address in $28 (exceptions expect it there) - * - * Outputs: - * bytes left to copy in $0 - * - * Clobbers: - * $1,$2,$3,$4,$5,$6 */ #include <asm/export.h> @@ -38,62 +23,63 @@ .set noreorder .align 4 - .globl __do_clear_user - .ent __do_clear_user - .frame $30, 0, $28 + .globl __clear_user + .ent __clear_user + .frame $30, 0, $26 .prologue 0 $loop: and $1, 3, $4 # e0 : beq $4, 1f # .. e1 : -0: EX( stq_u $31, 0($6) ) # e0 : zero one word +0: EX( stq_u $31, 0($16) ) # e0 : zero one word subq $0, 8, $0 # .. e1 : subq $4, 1, $4 # e0 : - addq $6, 8, $6 # .. e1 : + addq $16, 8, $16 # .. e1 : bne $4, 0b # e1 : unop # : 1: bic $1, 3, $1 # e0 : beq $1, $tail # .. e1 : -2: EX( stq_u $31, 0($6) ) # e0 : zero four words +2: EX( stq_u $31, 0($16) ) # e0 : zero four words subq $0, 8, $0 # .. e1 : - EX( stq_u $31, 8($6) ) # e0 : + EX( stq_u $31, 8($16) ) # e0 : subq $0, 8, $0 # .. e1 : - EX( stq_u $31, 16($6) ) # e0 : + EX( stq_u $31, 16($16) ) # e0 : subq $0, 8, $0 # .. e1 : - EX( stq_u $31, 24($6) ) # e0 : + EX( stq_u $31, 24($16) ) # e0 : subq $0, 8, $0 # .. e1 : subq $1, 4, $1 # e0 : - addq $6, 32, $6 # .. e1 : + addq $16, 32, $16 # .. e1 : bne $1, 2b # e1 : $tail: bne $2, 1f # e1 : is there a tail to do? - ret $31, ($28), 1 # .. e1 : + ret $31, ($26), 1 # .. e1 : -1: EX( ldq_u $5, 0($6) ) # e0 : +1: EX( ldq_u $5, 0($16) ) # e0 : clr $0 # .. e1 : nop # e1 : mskqh $5, $0, $5 # e0 : - EX( stq_u $5, 0($6) ) # e0 : - ret $31, ($28), 1 # .. e1 : + EX( stq_u $5, 0($16) ) # e0 : + ret $31, ($26), 1 # .. e1 : -__do_clear_user: - and $6, 7, $4 # e0 : find dest misalignment +__clear_user: + and $17, $17, $0 + and $16, 7, $4 # e0 : find dest misalignment beq $0, $zerolength # .. e1 : addq $0, $4, $1 # e0 : bias counter and $1, 7, $2 # e1 : number of bytes in tail srl $1, 3, $1 # e0 : beq $4, $loop # .. e1 : - EX( ldq_u $5, 0($6) ) # e0 : load dst word to mask back in + EX( ldq_u $5, 0($16) ) # e0 : load dst word to mask back in beq $1, $oneword # .. e1 : sub-word store? - mskql $5, $6, $5 # e0 : take care of misaligned head - addq $6, 8, $6 # .. e1 : - EX( stq_u $5, -8($6) ) # e0 : + mskql $5, $16, $5 # e0 : take care of misaligned head + addq $16, 8, $16 # .. e1 : + EX( stq_u $5, -8($16) ) # e0 : addq $0, $4, $0 # .. e1 : bytes left -= 8 - misalignment subq $1, 1, $1 # e0 : subq $0, 8, $0 # .. e1 : @@ -101,15 +87,15 @@ __do_clear_user: unop # : $oneword: - mskql $5, $6, $4 # e0 : + mskql $5, $16, $4 # e0 : mskqh $5, $2, $5 # e0 : or $5, $4, $5 # e1 : - EX( stq_u $5, 0($6) ) # e0 : + EX( stq_u $5, 0($16) ) # e0 : clr $0 # .. e1 : $zerolength: $exception: - ret $31, ($28), 1 # .. e1 : + ret $31, ($26), 1 # .. e1 : - .end __do_clear_user - EXPORT_SYMBOL(__do_clear_user) + .end __clear_user + EXPORT_SYMBOL(__clear_user) diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S index 509f62b65311..159f1b7e6e49 100644 --- a/arch/alpha/lib/copy_user.S +++ b/arch/alpha/lib/copy_user.S @@ -9,21 +9,6 @@ * contains the right "bytes left to copy" value (and that it is updated * only _after_ a successful copy). There is also some rather minor * exception setup stuff.. - * - * NOTE! This is not directly C-callable, because the calling semantics are - * different: - * - * Inputs: - * length in $0 - * destination address in $6 - * source address in $7 - * return address in $28 - * - * Outputs: - * bytes left to copy in $0 - * - * Clobbers: - * $1,$2,$3,$4,$5,$6,$7 */ #include <asm/export.h> @@ -49,58 +34,59 @@ .ent __copy_user __copy_user: .prologue 0 - and $6,7,$3 + and $18,$18,$0 + and $16,7,$3 beq $0,$35 beq $3,$36 subq $3,8,$3 .align 4 $37: - EXI( ldq_u $1,0($7) ) - EXO( ldq_u $2,0($6) ) - extbl $1,$7,$1 - mskbl $2,$6,$2 - insbl $1,$6,$1 + EXI( ldq_u $1,0($17) ) + EXO( ldq_u $2,0($16) ) + extbl $1,$17,$1 + mskbl $2,$16,$2 + insbl $1,$16,$1 addq $3,1,$3 bis $1,$2,$1 - EXO( stq_u $1,0($6) ) + EXO( stq_u $1,0($16) ) subq $0,1,$0 - addq $6,1,$6 - addq $7,1,$7 + addq $16,1,$16 + addq $17,1,$17 beq $0,$41 bne $3,$37 $36: - and $7,7,$1 + and $17,7,$1 bic $0,7,$4 beq $1,$43 beq $4,$48 - EXI( ldq_u $3,0($7) ) + EXI( ldq_u $3,0($17) ) .align 4 $50: - EXI( ldq_u $2,8($7) ) + EXI( ldq_u $2,8($17) ) subq $4,8,$4 - extql $3,$7,$3 - extqh $2,$7,$1 + extql $3,$17,$3 + extqh $2,$17,$1 bis $3,$1,$1 - EXO( stq $1,0($6) ) - addq $7,8,$7 + EXO( stq $1,0($16) ) + addq $17,8,$17 subq $0,8,$0 - addq $6,8,$6 + addq $16,8,$16 bis $2,$2,$3 bne $4,$50 $48: beq $0,$41 .align 4 $57: - EXI( ldq_u $1,0($7) ) - EXO( ldq_u $2,0($6) ) - extbl $1,$7,$1 - mskbl $2,$6,$2 - insbl $1,$6,$1 + EXI( ldq_u $1,0($17) ) + EXO( ldq_u $2,0($16) ) + extbl $1,$17,$1 + mskbl $2,$16,$2 + insbl $1,$16,$1 bis $1,$2,$1 - EXO( stq_u $1,0($6) ) + EXO( stq_u $1,0($16) ) subq $0,1,$0 - addq $6,1,$6 - addq $7,1,$7 + addq $16,1,$16 + addq $17,1,$17 bne $0,$57 br $31,$41 .align 4 @@ -108,27 +94,27 @@ $43: beq $4,$65 .align 4 $66: - EXI( ldq $1,0($7) ) + EXI( ldq $1,0($17) ) subq $4,8,$4 - EXO( stq $1,0($6) ) - addq $7,8,$7 + EXO( stq $1,0($16) ) + addq $17,8,$17 subq $0,8,$0 - addq $6,8,$6 + addq $16,8,$16 bne $4,$66 $65: beq $0,$41 - EXI( ldq $2,0($7) ) - EXO( ldq $1,0($6) ) + EXI( ldq $2,0($17) ) + EXO( ldq $1,0($16) ) mskql $2,$0,$2 mskqh $1,$0,$1 bis $2,$1,$2 - EXO( stq $2,0($6) ) + EXO( stq $2,0($16) ) bis $31,$31,$0 $41: $35: $exitin: $exitout: - ret $31,($28),1 + ret $31,($26),1 .end __copy_user EXPORT_SYMBOL(__copy_user) diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index 5dfb7975895f..ab42afba1720 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -45,10 +45,7 @@ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) __asm__ __volatile__( \ "1: ldq_u %0,%2\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - .\n" \ - " lda %0,2b-1b(%1)\n" \ - ".previous" \ + EXC(1b,2b,%0,%1) \ : "=r"(x), "=r"(__guu_err) \ : "m"(__m(ptr)), "1"(0)); \ __guu_err; \ @@ -60,10 +57,7 @@ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) __asm__ __volatile__( \ "1: stq_u %2,%1\n" \ "2:\n" \ - ".section __ex_table,\"a\"\n" \ - " .long 1b - ." \ - " lda $31,2b-1b(%0)\n" \ - ".previous" \ + EXC(1b,2b,$31,%0) \ : "=r"(__puu_err) \ : "m"(__m(addr)), "rJ"(x), "0"(0)); \ __puu_err; \ diff --git a/arch/alpha/lib/ev6-clear_user.S b/arch/alpha/lib/ev6-clear_user.S index 05bef6b50598..e179e4757ef8 100644 --- a/arch/alpha/lib/ev6-clear_user.S +++ b/arch/alpha/lib/ev6-clear_user.S @@ -9,21 +9,6 @@ * a successful copy). There is also some rather minor exception setup * stuff. * - * NOTE! This is not directly C-callable, because the calling semantics - * are different: - * - * Inputs: - * length in $0 - * destination address in $6 - * exception pointer in $7 - * return address in $28 (exceptions expect it there) - * - * Outputs: - * bytes left to copy in $0 - * - * Clobbers: - * $1,$2,$3,$4,$5,$6 - * * Much of the information about 21264 scheduling/coding comes from: * Compiler Writer's Guide for the Alpha 21264 * abbreviated as 'CWG' in other comments here @@ -56,14 +41,15 @@ .set noreorder .align 4 - .globl __do_clear_user - .ent __do_clear_user - .frame $30, 0, $28 + .globl __clear_user + .ent __clear_user + .frame $30, 0, $26 .prologue 0 # Pipeline info : Slotting & Comments -__do_clear_user: - and $6, 7, $4 # .. E .. .. : find dest head misalignment +__clear_user: + and $17, $17, $0 + and $16, 7, $4 # .. E .. .. : find dest head misalignment beq $0, $zerolength # U .. .. .. : U L U L addq $0, $4, $1 # .. .. .. E : bias counter @@ -75,14 +61,14 @@ __do_clear_user: /* * Head is not aligned. Write (8 - $4) bytes to head of destination - * This means $6 is known to be misaligned + * This means $16 is known to be misaligned */ - EX( ldq_u $5, 0($6) ) # .. .. .. L : load dst word to mask back in + EX( ldq_u $5, 0($16) ) # .. .. .. L : load dst word to mask back in beq $1, $onebyte # .. .. U .. : sub-word store? - mskql $5, $6, $5 # .. U .. .. : take care of misaligned head - addq $6, 8, $6 # E .. .. .. : L U U L + mskql $5, $16, $5 # .. U .. .. : take care of misaligned head + addq $16, 8, $16 # E .. .. .. : L U U L - EX( stq_u $5, -8($6) ) # .. .. .. L : + EX( stq_u $5, -8($16) ) # .. .. .. L : subq $1, 1, $1 # .. .. E .. : addq $0, $4, $0 # .. E .. .. : bytes left -= 8 - misalignment subq $0, 8, $0 # E .. .. .. : U L U L @@ -93,11 +79,11 @@ __do_clear_user: * values upon initial entry to the loop * $1 is number of quadwords to clear (zero is a valid value) * $2 is number of trailing bytes (0..7) ($2 never used...) - * $6 is known to be aligned 0mod8 + * $16 is known to be aligned 0mod8 */ $headalign: subq $1, 16, $4 # .. .. .. E : If < 16, we can not use the huge loop - and $6, 0x3f, $2 # .. .. E .. : Forward work for huge loop + and $16, 0x3f, $2 # .. .. E .. : Forward work for huge loop subq $2, 0x40, $3 # .. E .. .. : bias counter (huge loop) blt $4, $trailquad # U .. .. .. : U L U L @@ -114,21 +100,21 @@ $headalign: beq $3, $bigalign # U .. .. .. : U L U L : Aligned 0mod64 $alignmod64: - EX( stq_u $31, 0($6) ) # .. .. .. L + EX( stq_u $31, 0($16) ) # .. .. .. L addq $3, 8, $3 # .. .. E .. subq $0, 8, $0 # .. E .. .. nop # E .. .. .. : U L U L nop # .. .. .. E subq $1, 1, $1 # .. .. E .. - addq $6, 8, $6 # .. E .. .. + addq $16, 8, $16 # .. E .. .. blt $3, $alignmod64 # U .. .. .. : U L U L $bigalign: /* * $0 is the number of bytes left * $1 is the number of quads left - * $6 is aligned 0mod64 + * $16 is aligned 0mod64 * we know that we'll be taking a minimum of one trip through * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle * We are _not_ going to update $0 after every single store. That @@ -145,39 +131,39 @@ $bigalign: nop # E : nop # E : nop # E : - bis $6,$6,$3 # E : U L U L : Initial wh64 address is dest + bis $16,$16,$3 # E : U L U L : Initial wh64 address is dest /* This might actually help for the current trip... */ $do_wh64: wh64 ($3) # .. .. .. L1 : memory subsystem hint subq $1, 16, $4 # .. .. E .. : Forward calculation - repeat the loop? - EX( stq_u $31, 0($6) ) # .. L .. .. + EX( stq_u $31, 0($16) ) # .. L .. .. subq $0, 8, $0 # E .. .. .. : U L U L - addq $6, 128, $3 # E : Target address of wh64 - EX( stq_u $31, 8($6) ) # L : - EX( stq_u $31, 16($6) ) # L : + addq $16, 128, $3 # E : Target address of wh64 + EX( stq_u $31, 8($16) ) # L : + EX( stq_u $31, 16($16) ) # L : subq $0, 16, $0 # E : U L L U nop # E : - EX( stq_u $31, 24($6) ) # L : - EX( stq_u $31, 32($6) ) # L : + EX( stq_u $31, 24($16) ) # L : + EX( stq_u $31, 32($16) ) # L : subq $0, 168, $5 # E : U L L U : two trips through the loop left? /* 168 = 192 - 24, since we've already completed some stores */ subq $0, 16, $0 # E : - EX( stq_u $31, 40($6) ) # L : - EX( stq_u $31, 48($6) ) # L : - cmovlt $5, $6, $3 # E : U L L U : Latency 2, extra mapping cycle + EX( stq_u $31, 40($16) ) # L : + EX( stq_u $31, 48($16) ) # L : + cmovlt $5, $16, $3 # E : U L L U : Latency 2, extra mapping cycle subq $1, 8, $1 # E : subq $0, 16, $0 # E : - EX( stq_u $31, 56($6) ) # L : + EX( stq_u $31, 56($16) ) # L : nop # E : U L U L nop # E : subq $0, 8, $0 # E : - addq $6, 64, $6 # E : + addq $16, 64, $16 # E : bge $4, $do_wh64 # U : U L U L $trailquad: @@ -190,14 +176,14 @@ $trailquad: beq $1, $trailbytes # U .. .. .. : U L U L : Only 0..7 bytes to go $onequad: - EX( stq_u $31, 0($6) ) # .. .. .. L + EX( stq_u $31, 0($16) ) # .. .. .. L subq $1, 1, $1 # .. .. E .. subq $0, 8, $0 # .. E .. .. nop # E .. .. .. : U L U L nop # .. .. .. E nop # .. .. E .. - addq $6, 8, $6 # .. E .. .. + addq $16, 8, $16 # .. E .. .. bgt $1, $onequad # U .. .. .. : U L U L # We have an unknown number of bytes left to go. @@ -211,9 +197,9 @@ $trailbytes: # so we will use $0 as the loop counter # We know for a fact that $0 > 0 zero due to previous context $onebyte: - EX( stb $31, 0($6) ) # .. .. .. L + EX( stb $31, 0($16) ) # .. .. .. L subq $0, 1, $0 # .. .. E .. : - addq $6, 1, $6 # .. E .. .. : + addq $16, 1, $16 # .. E .. .. : bgt $0, $onebyte # U .. .. .. : U L U L $zerolength: @@ -221,6 +207,6 @@ $exception: # Destination for exception recovery(?) nop # .. .. .. E : nop # .. .. E .. : nop # .. E .. .. : - ret $31, ($28), 1 # L0 .. .. .. : L U L U - .end __do_clear_user - EXPORT_SYMBOL(__do_clear_user) + ret $31, ($26), 1 # L0 .. .. .. : L U L U + .end __clear_user + EXPORT_SYMBOL(__clear_user) diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S index be720b518af9..35e6710d0700 100644 --- a/arch/alpha/lib/ev6-copy_user.S +++ b/arch/alpha/lib/ev6-copy_user.S @@ -12,21 +12,6 @@ * only _after_ a successful copy). There is also some rather minor * exception setup stuff.. * - * NOTE! This is not directly C-callable, because the calling semantics are - * different: - * - * Inputs: - * length in $0 - * destination address in $6 - * source address in $7 - * return address in $28 - * - * Outputs: - * bytes left to copy in $0 - * - * Clobbers: - * $1,$2,$3,$4,$5,$6,$7 - * * Much of the information about 21264 scheduling/coding comes from: * Compiler Writer's Guide for the Alpha 21264 * abbreviated as 'CWG' in other comments here @@ -60,10 +45,11 @@ # Pipeline info: Slotting & Comments __copy_user: .prologue 0 - subq $0, 32, $1 # .. E .. .. : Is this going to be a small copy? + andq $18, $18, $0 + subq $18, 32, $1 # .. E .. .. : Is this going to be a small copy? beq $0, $zerolength # U .. .. .. : U L U L - and $6,7,$3 # .. .. .. E : is leading dest misalignment + and $16,7,$3 # .. .. .. E : is leading dest misalignment ble $1, $onebyteloop # .. .. U .. : 1st branch : small amount of data beq $3, $destaligned # .. U .. .. : 2nd (one cycle fetcher stall) subq $3, 8, $3 # E .. .. .. : L U U L : trip counter @@ -73,17 +59,17 @@ __copy_user: * We know we have at least one trip through this loop */ $aligndest: - EXI( ldbu $1,0($7) ) # .. .. .. L : Keep loads separate from stores - addq $6,1,$6 # .. .. E .. : Section 3.8 in the CWG + EXI( ldbu $1,0($17) ) # .. .. .. L : Keep loads separate from stores + addq $16,1,$16 # .. .. E .. : Section 3.8 in the CWG addq $3,1,$3 # .. E .. .. : nop # E .. .. .. : U L U L /* - * the -1 is to compensate for the inc($6) done in a previous quadpack + * the -1 is to compensate for the inc($16) done in a previous quadpack * which allows us zero dependencies within either quadpack in the loop */ - EXO( stb $1,-1($6) ) # .. .. .. L : - addq $7,1,$7 # .. .. E .. : Section 3.8 in the CWG + EXO( stb $1,-1($16) ) # .. .. .. L : + addq $17,1,$17 # .. .. E .. : Section 3.8 in the CWG subq $0,1,$0 # .. E .. .. : bne $3, $aligndest # U .. .. .. : U L U L @@ -92,29 +78,29 @@ $aligndest: * If we arrived via branch, we have a minimum of 32 bytes */ $destaligned: - and $7,7,$1 # .. .. .. E : Check _current_ source alignment + and $17,7,$1 # .. .. .. E : Check _current_ source alignment bic $0,7,$4 # .. .. E .. : number bytes as a quadword loop - EXI( ldq_u $3,0($7) ) # .. L .. .. : Forward fetch for fallthrough code + EXI( ldq_u $3,0($17) ) # .. L .. .. : Forward fetch for fallthrough code beq $1,$quadaligned # U .. .. .. : U L U L /* - * In the worst case, we've just executed an ldq_u here from 0($7) + * In the worst case, we've just executed an ldq_u here from 0($17) * and we'll repeat it once if we take the branch */ /* Misaligned quadword loop - not unrolled. Leave it that way. */ $misquad: - EXI( ldq_u $2,8($7) ) # .. .. .. L : + EXI( ldq_u $2,8($17) ) # .. .. .. L : subq $4,8,$4 # .. .. E .. : - extql $3,$7,$3 # .. U .. .. : - extqh $2,$7,$1 # U .. .. .. : U U L L + extql $3,$17,$3 # .. U .. .. : + extqh $2,$17,$1 # U .. .. .. : U U L L bis $3,$1,$1 # .. .. .. E : - EXO( stq $1,0($6) ) # .. .. L .. : - addq $7,8,$7 # .. E .. .. : + EXO( stq $1,0($16) ) # .. .. L .. : + addq $17,8,$17 # .. E .. .. : subq $0,8,$0 # E .. .. .. : U L L U - addq $6,8,$6 # .. .. .. E : + addq $16,8,$16 # .. .. .. E : bis $2,$2,$3 # .. .. E .. : nop # .. E .. .. : bne $4,$misquad # U .. .. .. : U L U L @@ -125,8 +111,8 @@ $misquad: beq $0,$zerolength # U .. .. .. : U L U L /* We know we have at least one trip through the byte loop */ - EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad - addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG) + EXI ( ldbu $2,0($17) ) # .. .. .. L : No loads in the same quad + addq $16,1,$16 # .. .. E .. : as the store (Section 3.8 in CWG) nop # .. E .. .. : br $31, $dirtyentry # L0 .. .. .. : L U U L /* Do the trailing byte loop load, then hop into the store part of the loop */ @@ -136,8 +122,8 @@ $misquad: * Based upon the usage context, it's worth the effort to unroll this loop * $0 - number of bytes to be moved * $4 - number of bytes to move as quadwords - * $6 is current destination address - * $7 is current source address + * $16 is current destination address + * $17 is current source address */ $quadaligned: subq $4, 32, $2 # .. .. .. E : do not unroll for small stuff @@ -155,29 +141,29 @@ $quadaligned: * instruction memory hint instruction). */ $unroll4: - EXI( ldq $1,0($7) ) # .. .. .. L - EXI( ldq $2,8($7) ) # .. .. L .. + EXI( ldq $1,0($17) ) # .. .. .. L + EXI( ldq $2,8($17) ) # .. .. L .. subq $4,32,$4 # .. E .. .. nop # E .. .. .. : U U L L - addq $7,16,$7 # .. .. .. E - EXO( stq $1,0($6) ) # .. .. L .. - EXO( stq $2,8($6) ) # .. L .. .. + addq $17,16,$17 # .. .. .. E + EXO( stq $1,0($16) ) # .. .. L .. + EXO( stq $2,8($16) ) # .. L .. .. subq $0,16,$0 # E .. .. .. : U L L U - addq $6,16,$6 # .. .. .. E - EXI( ldq $1,0($7) ) # .. .. L .. - EXI( ldq $2,8($7) ) # .. L .. .. + addq $16,16,$16 # .. .. .. E + EXI( ldq $1,0($17) ) # .. .. L .. + EXI( ldq $2,8($17) ) # .. L .. .. subq $4, 32, $3 # E .. .. .. : U U L L : is there enough for another trip? - EXO( stq $1,0($6) ) # .. .. .. L - EXO( stq $2,8($6) ) # .. .. L .. + EXO( stq $1,0($16) ) # .. .. .. L + EXO( stq $2,8($16) ) # .. .. L .. subq $0,16,$0 # .. E .. .. - addq $7,16,$7 # E .. .. .. : U L L U + addq $17,16,$17 # E .. .. .. : U L L U nop # .. .. .. E nop # .. .. E .. - addq $6,16,$6 # .. E .. .. + addq $16,16,$16 # .. E .. .. bgt $3,$unroll4 # U .. .. .. : U L U L nop @@ -186,14 +172,14 @@ $unroll4: beq $4, $noquads $onequad: - EXI( ldq $1,0($7) ) + EXI( ldq $1,0($17) ) subq $4,8,$4 - addq $7,8,$7 + addq $17,8,$17 nop - EXO( stq $1,0($6) ) + EXO( stq $1,0($16) ) subq $0,8,$0 - addq $6,8,$6 + addq $16,8,$16 bne $4,$onequad $noquads: @@ -207,23 +193,23 @@ $noquads: * There's no point in doing a lot of complex alignment calculations to try to * to quadword stuff for a small amount of data. * $0 - remaining number of bytes left to copy - * $6 - current dest addr - * $7 - current source addr + * $16 - current dest addr + * $17 - current source addr */ $onebyteloop: - EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad - addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG) + EXI ( ldbu $2,0($17) ) # .. .. .. L : No loads in the same quad + addq $16,1,$16 # .. .. E .. : as the store (Section 3.8 in CWG) nop # .. E .. .. : nop # E .. .. .. : U L U L $dirtyentry: /* - * the -1 is to compensate for the inc($6) done in a previous quadpack + * the -1 is to compensate for the inc($16) done in a previous quadpack * which allows us zero dependencies within either quadpack in the loop */ - EXO ( stb $2,-1($6) ) # .. .. .. L : - addq $7,1,$7 # .. .. E .. : quadpack as the load + EXO ( stb $2,-1($16) ) # .. .. .. L : + addq $17,1,$17 # .. .. E .. : quadpack as the load subq $0,1,$0 # .. E .. .. : change count _after_ copy bgt $0,$onebyteloop # U .. .. .. : U L U L @@ -233,7 +219,7 @@ $exitout: # Destination for exception recovery(?) nop # .. .. .. E nop # .. .. E .. nop # .. E .. .. - ret $31,($28),1 # L0 .. .. .. : L U L U + ret $31,($26),1 # L0 .. .. .. : L U L U .end __copy_user EXPORT_SYMBOL(__copy_user) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index c9f30f4763ab..5d7fb3e7cb97 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -406,6 +406,14 @@ config ARC_HAS_DIV_REM bool "Insn: div, divu, rem, remu" default y +config ARC_HAS_ACCL_REGS + bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6)" + default n + help + Depending on the configuration, CPU can contain accumulator reg-pair + (also referred to as r58:r59). These can also be used by gcc as GPR so + kernel needs to save/restore per process + endif # ISA_ARCV2 endmenu # "ARC CPU Configuration" diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi index 65808fe0a290..2891cb266cf0 100644 --- a/arch/arc/boot/dts/skeleton.dtsi +++ b/arch/arc/boot/dts/skeleton.dtsi @@ -26,6 +26,7 @@ device_type = "cpu"; compatible = "snps,arc770d"; reg = <0>; + clocks = <&core_clk>; }; }; diff --git a/arch/arc/boot/dts/skeleton_hs.dtsi b/arch/arc/boot/dts/skeleton_hs.dtsi index 2dfe8037dfbb..5e944d3e5b74 100644 --- a/arch/arc/boot/dts/skeleton_hs.dtsi +++ b/arch/arc/boot/dts/skeleton_hs.dtsi @@ -21,6 +21,7 @@ device_type = "cpu"; compatible = "snps,archs38"; reg = <0>; + clocks = <&core_clk>; }; }; diff --git a/arch/arc/boot/dts/skeleton_hs_idu.dtsi b/arch/arc/boot/dts/skeleton_hs_idu.dtsi index 4c11079f3565..54b277d7dea0 100644 --- a/arch/arc/boot/dts/skeleton_hs_idu.dtsi +++ b/arch/arc/boot/dts/skeleton_hs_idu.dtsi @@ -19,8 +19,27 @@ cpu@0 { device_type = "cpu"; - compatible = "snps,archs38xN"; + compatible = "snps,archs38"; reg = <0>; + clocks = <&core_clk>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <1>; + clocks = <&core_clk>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <2>; + clocks = <&core_clk>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <3>; + clocks = <&core_clk>; }; }; diff --git a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi index f0df59b23e21..459fc656b759 100644 --- a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi +++ b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi @@ -112,13 +112,19 @@ interrupts = <7>; bus-width = <4>; }; + }; - /* Embedded Vision subsystem UIO mappings; only relevant for EV VDK */ - uio_ev: uio@0xD0000000 { - compatible = "generic-uio"; - reg = <0xD0000000 0x2000 0xD1000000 0x2000 0x90000000 0x10000000 0xC0000000 0x10000000>; - reg-names = "ev_gsa", "ev_ctrl", "ev_shared_mem", "ev_code_mem"; - interrupts = <23>; - }; + /* + * Embedded Vision subsystem UIO mappings; only relevant for EV VDK + * + * This node is intentionally put outside of MB above becase + * it maps areas outside of MB's 0xEz-0xFz. + */ + uio_ev: uio@0xD0000000 { + compatible = "generic-uio"; + reg = <0xD0000000 0x2000 0xD1000000 0x2000 0x90000000 0x10000000 0xC0000000 0x10000000>; + reg-names = "ev_gsa", "ev_ctrl", "ev_shared_mem", "ev_code_mem"; + interrupt-parent = <&mb_intc>; + interrupts = <23>; }; }; diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 63a04013d05a..7bee4e4799fd 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -6,6 +6,7 @@ generic-y += device.h generic-y += div64.h generic-y += emergency-restart.h generic-y += errno.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += ftrace.h diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h index b65930a49589..54b54da6384c 100644 --- a/arch/arc/include/asm/atomic.h +++ b/arch/arc/include/asm/atomic.h @@ -17,10 +17,11 @@ #include <asm/barrier.h> #include <asm/smp.h> +#define ATOMIC_INIT(i) { (i) } + #ifndef CONFIG_ARC_PLAT_EZNPS #define atomic_read(v) READ_ONCE((v)->counter) -#define ATOMIC_INIT(i) { (i) } #ifdef CONFIG_ARC_HAS_LLSC diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index aee1a77934cf..ac85380d14a4 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -16,6 +16,11 @@ ; ; Now manually save: r12, sp, fp, gp, r25 +#ifdef CONFIG_ARC_HAS_ACCL_REGS + PUSH r59 + PUSH r58 +#endif + PUSH r30 PUSH r12 @@ -75,6 +80,11 @@ POP r12 POP r30 +#ifdef CONFIG_ARC_HAS_ACCL_REGS + POP r58 + POP r59 +#endif + .endm /*------------------------------------------------------------------------*/ diff --git a/arch/arc/include/asm/hugepage.h b/arch/arc/include/asm/hugepage.h index 317ff773e1ca..b18fcb606908 100644 --- a/arch/arc/include/asm/hugepage.h +++ b/arch/arc/include/asm/hugepage.h @@ -11,6 +11,7 @@ #define _ASM_ARC_HUGEPAGE_H #include <linux/types.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> static inline pte_t pmd_pte(pmd_t pmd) diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h index 00bdbe167615..2e52d18e6bc7 100644 --- a/arch/arc/include/asm/kprobes.h +++ b/arch/arc/include/asm/kprobes.h @@ -54,9 +54,7 @@ int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause); void kretprobe_trampoline(void); void trap_is_kprobe(unsigned long address, struct pt_regs *regs); #else -static void trap_is_kprobe(unsigned long address, struct pt_regs *regs) -{ -} +#define trap_is_kprobe(address, regs) #endif /* CONFIG_KPROBES */ #endif /* _ARC_KPROBES_H */ diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index e94ca72b974e..ee22d40afef4 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -37,6 +37,7 @@ #include <asm/page.h> #include <asm/mmu.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #include <linux/const.h> diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 47111d565a95..5297faa8a378 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -86,6 +86,10 @@ struct pt_regs { unsigned long r12, r30; +#ifdef CONFIG_ARC_HAS_ACCL_REGS + unsigned long r58, r59; /* ACCL/ACCH used by FPU / DSP MPY */ +#endif + /*------- Below list auto saved by h/w -----------*/ unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h index 41faf17cd28d..f35974ee7264 100644 --- a/arch/arc/include/asm/uaccess.h +++ b/arch/arc/include/asm/uaccess.h @@ -24,12 +24,10 @@ #ifndef _ASM_ARC_UACCESS_H #define _ASM_ARC_UACCESS_H -#include <linux/sched.h> -#include <asm/errno.h> #include <linux/string.h> /* for generic string functions */ -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) +#define __kernel_ok (uaccess_kernel()) /* * Algorithmically, for __user_ok() we want do: @@ -170,7 +168,7 @@ static inline unsigned long -__arc_copy_from_user(void *to, const void __user *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { long res = 0; char val; @@ -396,11 +394,8 @@ __arc_copy_from_user(void *to, const void __user *from, unsigned long n) return res; } -extern unsigned long slowpath_copy_to_user(void __user *to, const void *from, - unsigned long n); - static inline unsigned long -__arc_copy_to_user(void __user *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { long res = 0; char val; @@ -726,24 +721,20 @@ static inline long __arc_strnlen_user(const char __user *s, long n) } #ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE -#define __copy_from_user(t, f, n) __arc_copy_from_user(t, f, n) -#define __copy_to_user(t, f, n) __arc_copy_to_user(t, f, n) + +#define INLINE_COPY_TO_USER +#define INLINE_COPY_FROM_USER + #define __clear_user(d, n) __arc_clear_user(d, n) #define __strncpy_from_user(d, s, n) __arc_strncpy_from_user(d, s, n) #define __strnlen_user(s, n) __arc_strnlen_user(s, n) #else -extern long arc_copy_from_user_noinline(void *to, const void __user * from, - unsigned long n); -extern long arc_copy_to_user_noinline(void __user *to, const void *from, - unsigned long n); extern unsigned long arc_clear_user_noinline(void __user *to, unsigned long n); extern long arc_strncpy_from_user_noinline (char *dst, const char __user *src, long count); extern long arc_strnlen_user_noinline(const char __user *src, long n); -#define __copy_from_user(t, f, n) arc_copy_from_user_noinline(t, f, n) -#define __copy_to_user(t, f, n) arc_copy_to_user_noinline(t, f, n) #define __clear_user(d, n) arc_clear_user_noinline(d, n) #define __strncpy_from_user(d, s, n) arc_strncpy_from_user_noinline(d, s, n) #define __strnlen_user(s, n) arc_strnlen_user_noinline(s, n) @@ -752,6 +743,4 @@ extern long arc_strnlen_user_noinline(const char __user *src, long n); #include <asm-generic/uaccess.h> -extern int fixup_exception(struct pt_regs *regs); - #endif diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index 2585632eaa68..cc558a25b8fa 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -100,15 +100,21 @@ END(handle_interrupt) ;################### Non TLB Exception Handling ############################# ENTRY(EV_SWI) - flag 1 + ; TODO: implement this + EXCEPTION_PROLOGUE + b ret_from_exception END(EV_SWI) ENTRY(EV_DivZero) - flag 1 + ; TODO: implement this + EXCEPTION_PROLOGUE + b ret_from_exception END(EV_DivZero) ENTRY(EV_DCError) - flag 1 + ; TODO: implement this + EXCEPTION_PROLOGUE + b ret_from_exception END(EV_DCError) ; --------------------------------------------- diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 3093fa898a23..fc8211f338ad 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -10,6 +10,7 @@ #include <linux/fs.h> #include <linux/delay.h> #include <linux/root_dev.h> +#include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/clocksource.h> #include <linux/console.h> @@ -318,7 +319,8 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) static void arc_chk_core_config(void) { struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; - int fpu_enabled; + int saved = 0, present = 0; + char *opt_nm = NULL;; if (!cpu->extn.timer0) panic("Timer0 is not present!\n"); @@ -345,17 +347,28 @@ static void arc_chk_core_config(void) /* * FP hardware/software config sanity - * -If hardware contains DPFP, kernel needs to save/restore FPU state + * -If hardware present, kernel needs to save/restore FPU state * -If not, it will crash trying to save/restore the non-existant regs - * - * (only DPDP checked since SP has no arch visible regs) */ - fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE); - if (cpu->extn.fpu_dp && !fpu_enabled) - pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n"); - else if (!cpu->extn.fpu_dp && fpu_enabled) - panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n"); + if (is_isa_arcompact()) { + opt_nm = "CONFIG_ARC_FPU_SAVE_RESTORE"; + saved = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE); + + /* only DPDP checked since SP has no arch visible regs */ + present = cpu->extn.fpu_dp; + } else { + opt_nm = "CONFIG_ARC_HAS_ACCL_REGS"; + saved = IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS); + + /* Accumulator Low:High pair (r58:59) present if DSP MPY or FPU */ + present = cpu->extn_mpy.dsp | cpu->extn.fpu_sp | cpu->extn.fpu_dp; + } + + if (present && !saved) + pr_warn("Enable %s for working apps\n", opt_nm); + else if (!present && saved) + panic("Disable %s, hardware NOT present\n", opt_nm); } /* @@ -488,8 +501,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) { char *str; int cpu_id = ptr_to_cpu(v); - struct device_node *core_clk = of_find_node_by_name(NULL, "core_clk"); - u32 freq = 0; + struct device *cpu_dev = get_cpu_device(cpu_id); + struct clk *cpu_clk; + unsigned long freq = 0; if (!cpu_online(cpu_id)) { seq_printf(m, "processor [%d]\t: Offline\n", cpu_id); @@ -502,9 +516,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE)); - of_property_read_u32(core_clk, "clock-frequency", &freq); + cpu_clk = clk_get(cpu_dev, NULL); + if (IS_ERR(cpu_clk)) { + seq_printf(m, "CPU speed \t: Cannot get clock for processor [%d]\n", + cpu_id); + } else { + freq = clk_get_rate(cpu_clk); + } if (freq) - seq_printf(m, "CPU speed\t: %u.%02u Mhz\n", + seq_printf(m, "CPU speed\t: %lu.%02lu Mhz\n", freq / 1000000, (freq / 10000) % 100); seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n", diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index d408fa21a07c..928562967f3c 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -633,6 +633,9 @@ noinline static void slc_entire_op(const int op) write_aux_reg(ARC_REG_SLC_INVALIDATE, 1); + /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ + read_aux_reg(r); + /* Important to wait for flush to complete */ while (read_aux_reg(r) & SLC_CTRL_BUSY); } diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c index c86906b41bfe..72125a34e780 100644 --- a/arch/arc/mm/extable.c +++ b/arch/arc/mm/extable.c @@ -28,20 +28,6 @@ int fixup_exception(struct pt_regs *regs) #ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -long arc_copy_from_user_noinline(void *to, const void __user *from, - unsigned long n) -{ - return __arc_copy_from_user(to, from, n); -} -EXPORT_SYMBOL(arc_copy_from_user_noinline); - -long arc_copy_to_user_noinline(void __user *to, const void *from, - unsigned long n) -{ - return __arc_copy_to_user(to, from, n); -} -EXPORT_SYMBOL(arc_copy_to_user_noinline); - unsigned long arc_clear_user_noinline(void __user *to, unsigned long n) { diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0d4e71b42c77..8a7ab5e73af9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -41,7 +41,6 @@ config ARM select HARDIRQS_SW_RESEND select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 - select HAVE_ARCH_HARDENED_USERCOPY select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU select HAVE_ARCH_MMAP_RND_BITS if MMU diff --git a/arch/arm/boot/dts/am335x-baltos.dtsi b/arch/arm/boot/dts/am335x-baltos.dtsi index efb5eae290a8..d42b98f15e8b 100644 --- a/arch/arm/boot/dts/am335x-baltos.dtsi +++ b/arch/arm/boot/dts/am335x-baltos.dtsi @@ -371,6 +371,8 @@ phy1: ethernet-phy@1 { reg = <7>; + eee-broken-100tx; + eee-broken-1000t; }; }; diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 9e43c443738a..9ba4b18c0cb2 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -672,6 +672,7 @@ ti,non-removable; bus-width = <4>; cap-power-off-card; + keep-power-in-suspend; pinctrl-names = "default"; pinctrl-0 = <&mmc2_pins>; diff --git a/arch/arm/boot/dts/am335x-pcm-953.dtsi b/arch/arm/boot/dts/am335x-pcm-953.dtsi index 02981eae96b9..1ec8e0d80191 100644 --- a/arch/arm/boot/dts/am335x-pcm-953.dtsi +++ b/arch/arm/boot/dts/am335x-pcm-953.dtsi @@ -63,14 +63,14 @@ label = "home"; linux,code = <KEY_HOME>; gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>; - gpio-key,wakeup; + wakeup-source; }; button@1 { label = "menu"; linux,code = <KEY_MENU>; gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi index 0d341c545b01..e5ac1d81d15c 100644 --- a/arch/arm/boot/dts/am57xx-idk-common.dtsi +++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi @@ -315,6 +315,13 @@ /* ID & VBUS GPIOs provided in board dts */ }; }; + + tpic2810: tpic2810@60 { + compatible = "ti,tpic2810"; + reg = <0x60>; + gpio-controller; + #gpio-cells = <2>; + }; }; &mcspi3 { @@ -330,13 +337,6 @@ spi-max-frequency = <1000000>; spi-cpol; }; - - tpic2810: tpic2810@60 { - compatible = "ti,tpic2810"; - reg = <0x60>; - gpio-controller; - #gpio-cells = <2>; - }; }; &uart3 { diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index 0b4932cc02a8..c79c937b0a8a 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -42,18 +42,16 @@ }; mac0: ethernet@1e660000 { - compatible = "faraday,ftgmac100"; + compatible = "aspeed,ast2400-mac", "faraday,ftgmac100"; reg = <0x1e660000 0x180>; interrupts = <2>; - no-hw-checksum; status = "disabled"; }; mac1: ethernet@1e680000 { - compatible = "faraday,ftgmac100"; + compatible = "aspeed,ast2400-mac", "faraday,ftgmac100"; reg = <0x1e680000 0x180>; interrupts = <3>; - no-hw-checksum; status = "disabled"; }; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index b664fe380936..b6596633036c 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -33,18 +33,16 @@ }; mac0: ethernet@1e660000 { - compatible = "faraday,ftgmac100"; + compatible = "aspeed,ast2500-mac", "faraday,ftgmac100"; reg = <0x1e660000 0x180>; interrupts = <2>; - no-hw-checksum; status = "disabled"; }; mac1: ethernet@1e680000 { - compatible = "faraday,ftgmac100"; + compatible = "aspeed,ast2500-mac", "faraday,ftgmac100"; reg = <0x1e680000 0x180>; interrupts = <3>; - no-hw-checksum; status = "disabled"; }; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 4fbb089cf5ad..00de62dc0042 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -66,14 +66,14 @@ timer@20200 { compatible = "arm,cortex-a9-global-timer"; reg = <0x20200 0x100>; - interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>; clocks = <&periph_clk>; }; local-timer@20600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0x20600 0x100>; - interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_PPI 13 IRQ_TYPE_EDGE_RISING>; clocks = <&periph_clk>; }; diff --git a/arch/arm/boot/dts/bcm953012k.dts b/arch/arm/boot/dts/bcm953012k.dts index bfd923096a8c..ae31a5826e91 100644 --- a/arch/arm/boot/dts/bcm953012k.dts +++ b/arch/arm/boot/dts/bcm953012k.dts @@ -48,15 +48,14 @@ }; memory { - reg = <0x00000000 0x10000000>; + reg = <0x80000000 0x10000000>; }; }; &uart0 { - clock-frequency = <62499840>; + status = "okay"; }; &uart1 { - clock-frequency = <62499840>; status = "okay"; }; diff --git a/arch/arm/boot/dts/bcm958522er.dts b/arch/arm/boot/dts/bcm958522er.dts index 3f04a40eb90c..df05e7f568af 100644 --- a/arch/arm/boot/dts/bcm958522er.dts +++ b/arch/arm/boot/dts/bcm958522er.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958525er.dts b/arch/arm/boot/dts/bcm958525er.dts index 9fd542200d3d..4a3ab19c6281 100644 --- a/arch/arm/boot/dts/bcm958525er.dts +++ b/arch/arm/boot/dts/bcm958525er.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958525xmc.dts b/arch/arm/boot/dts/bcm958525xmc.dts index 41e7fd350fcd..81f78435d8c7 100644 --- a/arch/arm/boot/dts/bcm958525xmc.dts +++ b/arch/arm/boot/dts/bcm958525xmc.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 31 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958622hr.dts b/arch/arm/boot/dts/bcm958622hr.dts index 477c4860db52..c88b8fefcb2f 100644 --- a/arch/arm/boot/dts/bcm958622hr.dts +++ b/arch/arm/boot/dts/bcm958622hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958623hr.dts b/arch/arm/boot/dts/bcm958623hr.dts index c0a499d5ba44..d503fa0dde31 100644 --- a/arch/arm/boot/dts/bcm958623hr.dts +++ b/arch/arm/boot/dts/bcm958623hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958625hr.dts b/arch/arm/boot/dts/bcm958625hr.dts index f7eb5854a224..cc0363b843c1 100644 --- a/arch/arm/boot/dts/bcm958625hr.dts +++ b/arch/arm/boot/dts/bcm958625hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm988312hr.dts b/arch/arm/boot/dts/bcm988312hr.dts index 16666324fda8..74e15a3cd9f8 100644 --- a/arch/arm/boot/dts/bcm988312hr.dts +++ b/arch/arm/boot/dts/bcm988312hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 2c9e56f4aac5..bbfb9d5a70a9 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -283,6 +283,7 @@ device_type = "pci"; ranges = <0x81000000 0 0 0x03000 0 0x00010000 0x82000000 0 0x20013000 0x13000 0 0xffed000>; + bus-range = <0x00 0xff>; #interrupt-cells = <1>; num-lanes = <1>; linux,pci-domain = <0>; @@ -319,6 +320,7 @@ device_type = "pci"; ranges = <0x81000000 0 0 0x03000 0 0x00010000 0x82000000 0 0x30013000 0x13000 0 0xffed000>; + bus-range = <0x00 0xff>; #interrupt-cells = <1>; num-lanes = <1>; linux,pci-domain = <1>; diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi index 49f466fe0b1d..dcfc97591433 100644 --- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi +++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi @@ -121,11 +121,6 @@ }; }; -&cpu0 { - arm-supply = <&sw1a_reg>; - soc-supply = <&sw1c_reg>; -}; - &fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet1>; diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi index 8f9a69ca818c..efe53998c961 100644 --- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi +++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi @@ -121,7 +121,7 @@ &i2c3 { clock-frequency = <400000>; at24@50 { - compatible = "at24,24c02"; + compatible = "atmel,24c64"; readonly; reg = <0x50>; }; diff --git a/arch/arm/boot/dts/rk1108.dtsi b/arch/arm/boot/dts/rk1108.dtsi index d6194bff7afe..6c8fc19d0ecd 100644 --- a/arch/arm/boot/dts/rk1108.dtsi +++ b/arch/arm/boot/dts/rk1108.dtsi @@ -222,7 +222,7 @@ }; pinctrl: pinctrl { - compatible = "rockchip,rk1108-pinctrl"; + compatible = "rockchip,rv1108-pinctrl"; rockchip,grf = <&grf>; rockchip,pmu = <&pmugrf>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index cf91254d0a43..1aff4ad22fc4 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -106,6 +106,22 @@ }; }; + timer3: timer@2000e000 { + compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; + reg = <0x2000e000 0x20>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_TIMER3>, <&cru PCLK_TIMER3>; + clock-names = "timer", "pclk"; + }; + + timer6: timer@200380a0 { + compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; + reg = <0x200380a0 0x20>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_TIMER6>, <&cru PCLK_TIMER0>; + clock-names = "timer", "pclk"; + }; + i2s0: i2s@1011a000 { compatible = "rockchip,rk3188-i2s", "rockchip,rk3066-i2s"; reg = <0x1011a000 0x2000>; @@ -530,6 +546,7 @@ &global_timer { interrupts = <GIC_PPI 11 0xf04>; + status = "disabled"; }; &local_timer { diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 9dff8221112c..641607d9ad29 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -325,7 +325,7 @@ }; timer: timer@110c0000 { - compatible = "rockchip,rk3288-timer"; + compatible = "rockchip,rk3228-timer", "rockchip,rk3288-timer"; reg = <0x110c0000 0x20>; interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; clocks = <&xin24m>, <&cru PCLK_TIMER>; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 22332be72140..528b4e9c6d3d 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -266,7 +266,7 @@ }; usb1: ohci@00400000 { - compatible = "atmel,sama5d2-ohci", "usb-ohci"; + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00400000 0x100000>; interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 82d8c4771293..6c5affe2d0f5 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -14,6 +14,7 @@ #include <dt-bindings/mfd/dbx500-prcmu.h> #include <dt-bindings/arm/ux500_pm_domains.h> #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/clock/ste-ab8500.h> #include "skeleton.dtsi" / { @@ -603,6 +604,11 @@ interrupt-controller; #interrupt-cells = <2>; + ab8500_clock: clock-controller { + compatible = "stericsson,ab8500-clk"; + #clock-cells = <1>; + }; + ab8500_gpio: ab8500-gpio { compatible = "stericsson,ab8500-gpio"; gpio-controller; @@ -686,6 +692,8 @@ ab8500-pwm { compatible = "stericsson,ab8500-pwm"; + clocks = <&ab8500_clock AB8500_SYSCLK_INT>; + clock-names = "intclk"; }; ab8500-debugfs { @@ -700,6 +708,9 @@ V-AMIC2-supply = <&ab8500_ldo_anamic2_reg>; V-DMIC-supply = <&ab8500_ldo_dmic_reg>; + clocks = <&ab8500_clock AB8500_SYSCLK_AUDIO>; + clock-names = "audioclk"; + stericsson,earpeice-cmv = <950>; /* Units in mV. */ }; @@ -1095,6 +1106,14 @@ status = "disabled"; }; + sound { + compatible = "stericsson,snd-soc-mop500"; + stericsson,cpu-dai = <&msp1 &msp3>; + stericsson,audio-codec = <&codec>; + clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>; + clock-names = "sysclk", "ulpclk", "intclk"; + }; + msp0: msp@80123000 { compatible = "stericsson,ux500-msp-i2s"; reg = <0x80123000 0x1000>; @@ -1170,11 +1189,6 @@ status = "disabled"; }; - cpufreq-cooling { - compatible = "stericsson,db8500-cpufreq-cooling"; - status = "disabled"; - }; - mcde@a0350000 { compatible = "stericsson,mcde"; reg = <0xa0350000 0x1000>, /* MCDE */ diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index f37f9e10713c..9e359e4f342e 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -186,15 +186,6 @@ status = "okay"; }; - sound { - compatible = "stericsson,snd-soc-mop500"; - - stericsson,cpu-dai = <&msp1 &msp3>; - stericsson,audio-codec = <&codec>; - clocks = <&prcmu_clk PRCMU_SYSCLK>; - clock-names = "sysclk"; - }; - msp0: msp@80123000 { pinctrl-names = "default"; pinctrl-0 = <&msp0_default_mode>; diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts index dd5514def604..ade1d0d4e5f4 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/ste-snowball.dts @@ -159,15 +159,6 @@ "", "", "", "", "", "", "", ""; }; - sound { - compatible = "stericsson,snd-soc-mop500"; - - stericsson,cpu-dai = <&msp1 &msp3>; - stericsson,audio-codec = <&codec>; - clocks = <&prcmu_clk PRCMU_SYSCLK>; - clock-names = "sysclk"; - }; - msp0: msp@80123000 { pinctrl-names = "default"; pinctrl-0 = <&msp0_default_mode>; diff --git a/arch/arm/boot/dts/stm32746g-eval.dts b/arch/arm/boot/dts/stm32746g-eval.dts index aa03fac1ec55..0dc18a0f0940 100644 --- a/arch/arm/boot/dts/stm32746g-eval.dts +++ b/arch/arm/boot/dts/stm32746g-eval.dts @@ -89,6 +89,10 @@ clock-frequency = <25000000>; }; +&crc { + status = "okay"; +}; + &usart1 { pinctrl-0 = <&usart1_pins_a>; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi index f321ffe87144..755fb923c07b 100644 --- a/arch/arm/boot/dts/stm32f746.dtsi +++ b/arch/arm/boot/dts/stm32f746.dtsi @@ -289,6 +289,13 @@ }; }; + crc: crc@40023000 { + compatible = "st,stm32f7-crc"; + reg = <0x40023000 0x400>; + clocks = <&rcc 0 12>; + status = "disabled"; + }; + rcc: rcc@40023800 { #clock-cells = <2>; compatible = "st,stm32f42xx-rcc", "st,stm32-rcc"; diff --git a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts index 72ec0d5ae052..bbf1c8cbaac6 100644 --- a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts +++ b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts @@ -167,7 +167,7 @@ reg = <8>; label = "cpu"; ethernet = <&gmac>; - phy-mode = "rgmii"; + phy-mode = "rgmii-txid"; fixed-link { speed = <1000>; full-duplex; diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index a952cc0703cc..8a3ed21cb7bc 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -495,7 +495,7 @@ resets = <&ccu RST_BUS_GPU>; assigned-clocks = <&ccu CLK_GPU>; - assigned-clock-rates = <408000000>; + assigned-clock-rates = <384000000>; }; gic: interrupt-controller@01c81000 { diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index 18c174fef84f..306af6cadf26 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -66,12 +66,6 @@ opp-microvolt = <1200000>; clock-latency-ns = <244144>; /* 8 32k periods */ }; - - opp@1200000000 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <1320000>; - clock-latency-ns = <244144>; /* 8 32k periods */ - }; }; cpus { @@ -81,16 +75,22 @@ operating-points-v2 = <&cpu0_opp_table>; }; + cpu@1 { + operating-points-v2 = <&cpu0_opp_table>; + }; + cpu@2 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <2>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu@3 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <3>; + operating-points-v2 = <&cpu0_opp_table>; }; }; @@ -113,8 +113,8 @@ simple-audio-card,mclk-fs = <512>; simple-audio-card,aux-devs = <&codec_analog>; simple-audio-card,routing = - "Left DAC", "Digital Left DAC", - "Right DAC", "Digital Right DAC"; + "Left DAC", "AIF1 Slot 0 Left", + "Right DAC", "AIF1 Slot 0 Right"; status = "disabled"; simple-audio-card,cpu { diff --git a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi index 7097c18ff487..d6bd15898db6 100644 --- a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi +++ b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi @@ -50,8 +50,6 @@ backlight: backlight { compatible = "pwm-backlight"; - pinctrl-names = "default"; - pinctrl-0 = <&bl_en_pin>; pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; default-brightness-level = <8>; @@ -93,11 +91,6 @@ }; &pio { - bl_en_pin: bl_en_pin@0 { - pins = "PH6"; - function = "gpio_in"; - }; - mmc0_cd_pin: mmc0_cd_pin@0 { pins = "PB4"; function = "gpio_in"; diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index a94126fb02c2..6aa7be191f1a 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -748,7 +748,6 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_TRANSIENT=y CONFIG_LEDS_TRIGGER_CAMERA=y CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_HIGHBANK_MC=y CONFIG_EDAC_HIGHBANK_L2=y CONFIG_RTC_CLASS=y diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index f2462a6bdba6..decd388d613d 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -188,6 +188,7 @@ CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m +CONFIG_INPUT_MOUSEDEV=m CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=m CONFIG_KEYBOARD_ATKBD=m diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index 2aac99fd1c41..1318f61589dc 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -635,8 +635,7 @@ CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_LEDS_TRIGGER_TRANSIENT=m CONFIG_LEDS_TRIGGER_CAMERA=m -CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC=m CONFIG_RTC_CLASS=y CONFIG_RTC_DEBUG=y CONFIG_RTC_DRV_DS1307=m diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig index a9d8e3c9b487..03437f8f9ad1 100644 --- a/arch/arm/configs/stm32_defconfig +++ b/arch/arm/configs/stm32_defconfig @@ -75,5 +75,7 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_SCHED_DEBUG is not set # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_FTRACE is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_DEV_STM32=y CONFIG_CRC_ITU_T=y CONFIG_CRC7=y diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index a8fce93137fb..b9adedcc5b2e 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -73,7 +73,7 @@ config CRYPTO_AES_ARM_BS depends on KERNEL_MODE_NEON select CRYPTO_BLKCIPHER select CRYPTO_SIMD - select CRYPTO_AES_ARM + select CRYPTO_AES help Use a faster and more secure NEON based implementation of AES in CBC, CTR and XTS modes diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index 2920b96dbd36..c76377961444 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -42,9 +42,6 @@ asmlinkage void aesbs_xts_encrypt(u8 out[], u8 const in[], u8 const rk[], asmlinkage void aesbs_xts_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, int blocks, u8 iv[]); -asmlinkage void __aes_arm_encrypt(const u32 rk[], int rounds, const u8 in[], - u8 out[]); - struct aesbs_ctx { int rounds; u8 rk[13 * (8 * AES_BLOCK_SIZE) + 32] __aligned(AES_BLOCK_SIZE); @@ -52,12 +49,12 @@ struct aesbs_ctx { struct aesbs_cbc_ctx { struct aesbs_ctx key; - u32 enc[AES_MAX_KEYLENGTH_U32]; + struct crypto_cipher *enc_tfm; }; struct aesbs_xts_ctx { struct aesbs_ctx key; - u32 twkey[AES_MAX_KEYLENGTH_U32]; + struct crypto_cipher *tweak_tfm; }; static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, @@ -132,20 +129,18 @@ static int aesbs_cbc_setkey(struct crypto_skcipher *tfm, const u8 *in_key, ctx->key.rounds = 6 + key_len / 4; - memcpy(ctx->enc, rk.key_enc, sizeof(ctx->enc)); - kernel_neon_begin(); aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds); kernel_neon_end(); - return 0; + return crypto_cipher_setkey(ctx->enc_tfm, in_key, key_len); } static void cbc_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst) { struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); - __aes_arm_encrypt(ctx->enc, ctx->key.rounds, src, dst); + crypto_cipher_encrypt_one(ctx->enc_tfm, dst, src); } static int cbc_encrypt(struct skcipher_request *req) @@ -181,6 +176,23 @@ static int cbc_decrypt(struct skcipher_request *req) return err; } +static int cbc_init(struct crypto_tfm *tfm) +{ + struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->enc_tfm = crypto_alloc_cipher("aes", 0, 0); + if (IS_ERR(ctx->enc_tfm)) + return PTR_ERR(ctx->enc_tfm); + return 0; +} + +static void cbc_exit(struct crypto_tfm *tfm) +{ + struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_cipher(ctx->enc_tfm); +} + static int ctr_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -228,7 +240,6 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_aes_ctx rk; int err; err = xts_verify_key(tfm, in_key, key_len); @@ -236,15 +247,30 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, return err; key_len /= 2; - err = crypto_aes_expand_key(&rk, in_key + key_len, key_len); + err = crypto_cipher_setkey(ctx->tweak_tfm, in_key + key_len, key_len); if (err) return err; - memcpy(ctx->twkey, rk.key_enc, sizeof(ctx->twkey)); - return aesbs_setkey(tfm, in_key, key_len); } +static int xts_init(struct crypto_tfm *tfm) +{ + struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->tweak_tfm = crypto_alloc_cipher("aes", 0, 0); + if (IS_ERR(ctx->tweak_tfm)) + return PTR_ERR(ctx->tweak_tfm); + return 0; +} + +static void xts_exit(struct crypto_tfm *tfm) +{ + struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_cipher(ctx->tweak_tfm); +} + static int __xts_crypt(struct skcipher_request *req, void (*fn)(u8 out[], u8 const in[], u8 const rk[], int rounds, int blocks, u8 iv[])) @@ -256,7 +282,7 @@ static int __xts_crypt(struct skcipher_request *req, err = skcipher_walk_virt(&walk, req, true); - __aes_arm_encrypt(ctx->twkey, ctx->key.rounds, walk.iv, walk.iv); + crypto_cipher_encrypt_one(ctx->tweak_tfm, walk.iv, walk.iv); kernel_neon_begin(); while (walk.nbytes >= AES_BLOCK_SIZE) { @@ -309,6 +335,8 @@ static struct skcipher_alg aes_algs[] = { { .base.cra_ctxsize = sizeof(struct aesbs_cbc_ctx), .base.cra_module = THIS_MODULE, .base.cra_flags = CRYPTO_ALG_INTERNAL, + .base.cra_init = cbc_init, + .base.cra_exit = cbc_exit, .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, @@ -342,6 +370,8 @@ static struct skcipher_alg aes_algs[] = { { .base.cra_ctxsize = sizeof(struct aesbs_xts_ctx), .base.cra_module = THIS_MODULE, .base.cra_flags = CRYPTO_ALG_INTERNAL, + .base.cra_init = xts_init, + .base.cra_exit = xts_exit, .min_keysize = 2 * AES_MIN_KEY_SIZE, .max_keysize = 2 * AES_MAX_KEY_SIZE, @@ -402,5 +432,5 @@ unregister_simds: return err; } -module_init(aes_init); +late_initcall(aes_init); module_exit(aes_exit); diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index b14e8c7d71bd..3a36d99ff836 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -7,6 +7,7 @@ generic-y += early_ioremap.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += ioctl.h generic-y += ipcbuf.h generic-y += irq_regs.h diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index e4e6a9d6a825..17f1f1a814ff 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) */ #define ZIMAGE_OFFSET_LIMIT SZ_128M #define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE -#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT + +/* on ARM, the FDT should be located in the first 128 MB of RAM */ +static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) +{ + return dram_base + ZIMAGE_OFFSET_LIMIT; +} + +/* on ARM, the initrd should be loaded in a lowmem region */ +static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, + unsigned long image_addr) +{ + return dram_base + SZ_512M; +} #endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h index e22089fb44dc..a3f0b3d50089 100644 --- a/arch/arm/include/asm/kvm_arm.h +++ b/arch/arm/include/asm/kvm_arm.h @@ -209,6 +209,7 @@ #define HSR_EC_IABT_HYP (0x21) #define HSR_EC_DABT (0x24) #define HSR_EC_DABT_HYP (0x25) +#define HSR_EC_MAX (0x3f) #define HSR_WFI_IS_WFE (_AC(1, UL) << 0) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index cc495d799c67..31ee468ce667 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -30,7 +30,6 @@ #define __KVM_HAVE_ARCH_INTC_INITIALIZED #define KVM_USER_MEM_SLOTS 32 -#define KVM_PRIVATE_MEM_SLOTS 4 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG #define KVM_HALT_POLL_NS_DEFAULT 500000 diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a8d656d9aec7..1c462381c225 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -20,6 +20,7 @@ #else +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> #include <asm/memory.h> #include <asm/pgtable-hwdef.h> diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index b7e0125c0bbf..2577405d082d 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -12,8 +12,6 @@ * User space memory access functions */ #include <linux/string.h> -#include <linux/thread_info.h> -#include <asm/errno.h> #include <asm/memory.h> #include <asm/domain.h> #include <asm/unified.h> @@ -26,28 +24,7 @@ #define __put_user_unaligned __put_user #endif -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * 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; -}; - -extern int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> /* * These two functions allow hooking accesses to userspace to increase @@ -271,7 +248,7 @@ static inline void set_fs(mm_segment_t fs) #define access_ok(type, addr, size) (__range_ok(addr, size) == 0) #define user_addr_max() \ - (segment_eq(get_fs(), KERNEL_DS) ? ~0UL : get_fs()) + (uaccess_kernel() ? ~0UL : get_fs()) /* * The "__xxx" versions of the user access functions do not verify the @@ -478,7 +455,7 @@ extern unsigned long __must_check arm_copy_from_user(void *to, const void __user *from, unsigned long n); static inline unsigned long __must_check -__arch_copy_from_user(void *to, const void __user *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned int __ua_flags; @@ -494,7 +471,7 @@ extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n); static inline unsigned long __must_check -__arch_copy_to_user(void __user *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { #ifndef CONFIG_UACCESS_WITH_MEMCPY unsigned int __ua_flags; @@ -522,54 +499,22 @@ __clear_user(void __user *addr, unsigned long n) } #else -#define __arch_copy_from_user(to, from, n) \ - (memcpy(to, (void __force *)from, n), 0) -#define __arch_copy_to_user(to, from, n) \ - (memcpy((void __force *)to, from, n), 0) -#define __clear_user(addr, n) (memset((void __force *)addr, 0, n), 0) -#endif - -static inline unsigned long __must_check -__copy_from_user(void *to, const void __user *from, unsigned long n) -{ - check_object_size(to, n, false); - return __arch_copy_from_user(to, from, n); -} - -static inline unsigned long __must_check -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - unsigned long res = n; - - check_object_size(to, n, false); - - if (likely(access_ok(VERIFY_READ, from, n))) - res = __arch_copy_from_user(to, from, n); - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; -} - -static inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - check_object_size(from, n, true); - - return __arch_copy_to_user(to, from, n); + memcpy(to, (const void __force *)from, n); + return 0; } - -static inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - check_object_size(from, n, true); - - if (access_ok(VERIFY_WRITE, to, n)) - n = __arch_copy_to_user(to, from, n); - return n; + memcpy((void __force *)to, from, n); + return 0; } - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#define __clear_user(addr, n) (memset((void __force *)addr, 0, n), 0) +#endif +#define INLINE_COPY_TO_USER +#define INLINE_COPY_FROM_USER static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) { diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 37b2a11af345..8265b116218d 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -242,6 +242,8 @@ SECTIONS } _edata_loc = __data_loc + SIZEOF(.data); + BUG_TABLE + #ifdef CONFIG_HAVE_TCM /* * We align everything to a page boundary so we can diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index ce18007f9e4e..c83a7ba737d6 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -262,6 +262,8 @@ SECTIONS } _edata_loc = __data_loc + SIZEOF(.data); + BUG_TABLE + #ifdef CONFIG_HAVE_TCM /* * We align everything to a page boundary so we can diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index c9a2103faeb9..314eb6abe1ff 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -221,6 +221,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_MAX_VCPUS: r = KVM_MAX_VCPUS; break; + case KVM_CAP_NR_MEMSLOTS: + r = KVM_USER_MEM_SLOTS; + break; case KVM_CAP_MSI_DEVID: if (!kvm) r = -EINVAL; @@ -1121,6 +1124,9 @@ static void cpu_hyp_reinit(void) if (__hyp_get_vectors() == hyp_default_vectors) cpu_init_hyp_mode(NULL); } + + if (vgic_present) + kvm_vgic_init_cpu_hardware(); } static void cpu_hyp_reset(void) diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 4e40d1955e35..96af65a30d78 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -79,7 +79,19 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } +static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + u32 hsr = kvm_vcpu_get_hsr(vcpu); + + kvm_pr_unimpl("Unknown exception class: hsr: %#08x\n", + hsr); + + kvm_inject_undefined(vcpu); + return 1; +} + static exit_handle_fn arm_exit_handlers[] = { + [0 ... HSR_EC_MAX] = kvm_handle_unknown_ec, [HSR_EC_WFI] = kvm_handle_wfx, [HSR_EC_CP15_32] = kvm_handle_cp15_32, [HSR_EC_CP15_64] = kvm_handle_cp15_64, @@ -98,13 +110,6 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) { u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu); - if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || - !arm_exit_handlers[hsr_ec]) { - kvm_err("Unknown exception class: hsr: %#08x\n", - (unsigned int)kvm_vcpu_get_hsr(vcpu)); - BUG(); - } - return arm_exit_handlers[hsr_ec]; } diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 962616fd4ddd..582a972371cf 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -292,11 +292,18 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) phys_addr_t addr = start, end = start + size; phys_addr_t next; + assert_spin_locked(&kvm->mmu_lock); pgd = kvm->arch.pgd + stage2_pgd_index(addr); do { next = stage2_pgd_addr_end(addr, end); if (!stage2_pgd_none(*pgd)) unmap_stage2_puds(kvm, pgd, addr, next); + /* + * If the range is too large, release the kvm->mmu_lock + * to prevent starvation and lockup detector warnings. + */ + if (next != end) + cond_resched_lock(&kvm->mmu_lock); } while (pgd++, addr = next, addr != end); } @@ -803,6 +810,7 @@ void stage2_unmap_vm(struct kvm *kvm) int idx; idx = srcu_read_lock(&kvm->srcu); + down_read(¤t->mm->mmap_sem); spin_lock(&kvm->mmu_lock); slots = kvm_memslots(kvm); @@ -810,6 +818,7 @@ void stage2_unmap_vm(struct kvm *kvm) stage2_unmap_memslot(kvm, memslot); spin_unlock(&kvm->mmu_lock); + up_read(¤t->mm->mmap_sem); srcu_read_unlock(&kvm->srcu, idx); } @@ -829,7 +838,10 @@ void kvm_free_stage2_pgd(struct kvm *kvm) if (kvm->arch.pgd == NULL) return; + spin_lock(&kvm->mmu_lock); unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); + spin_unlock(&kvm->mmu_lock); + /* Free the HW pgd, one page at a time */ free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE); kvm->arch.pgd = NULL; @@ -1801,6 +1813,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, (KVM_PHYS_SIZE >> PAGE_SHIFT)) return -EFAULT; + down_read(¤t->mm->mmap_sem); /* * A memory region could potentially cover multiple VMAs, and any holes * between them, so iterate over all of them to find out if we can map @@ -1844,8 +1857,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, pa += vm_start - vma->vm_start; /* IO region dirty page logging not allowed */ - if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) - return -EINVAL; + if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) { + ret = -EINVAL; + goto out; + } ret = kvm_phys_addr_ioremap(kvm, gpa, pa, vm_end - vm_start, @@ -1857,7 +1872,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, } while (hva < reg_end); if (change == KVM_MR_FLAGS_ONLY) - return ret; + goto out; spin_lock(&kvm->mmu_lock); if (ret) @@ -1865,6 +1880,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, else stage2_flush_memslot(kvm, memslot); spin_unlock(&kvm->mmu_lock); +out: + up_read(¤t->mm->mmap_sem); return ret; } diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index 6bd1089b07e0..9b4ed1728616 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -90,7 +90,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) unsigned long ua_flags; int atomic; - if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { + if (uaccess_kernel()) { memcpy((void *)to, from, n); return 0; } @@ -162,7 +162,7 @@ __clear_user_memset(void __user *addr, unsigned long n) { unsigned long ua_flags; - if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { + if (uaccess_kernel()) { memset((void *)addr, 0, n); return 0; } diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 3d89b7905bd9..a277981f414d 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -289,6 +289,22 @@ static void at91_ddr_standby(void) at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); } +static void sama5d3_ddr_standby(void) +{ + u32 lpr0; + u32 saved_lpr0; + + saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); + lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB; + lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN; + + at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); + + cpu_do_idle(); + + at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); +} + /* We manage both DDRAM/SDRAM controllers, we need more than one value to * remember. */ @@ -323,7 +339,7 @@ static const struct of_device_id const ramc_ids[] __initconst = { { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, - { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby }, + { .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby }, { /*sentinel*/ } }; diff --git a/arch/arm/mach-moxart/Kconfig b/arch/arm/mach-moxart/Kconfig index f69e28b85e88..70db2abf6163 100644 --- a/arch/arm/mach-moxart/Kconfig +++ b/arch/arm/mach-moxart/Kconfig @@ -3,8 +3,8 @@ menuconfig ARCH_MOXART depends on ARCH_MULTI_V4 select CPU_FA526 select ARM_DMA_MEM_BUFFERABLE + select FARADAY_FTINTC010 select MOXART_TIMER - select GENERIC_IRQ_CHIP select GPIOLIB select PHYLIB if NETDEVICES help diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 093458b62c8d..c89757abb0ae 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -241,6 +241,3 @@ obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o obj-y += $(onenand-m) $(onenand-y) - -nand-$(CONFIG_MTD_NAND_OMAP2) := gpmc-nand.o -obj-y += $(nand-m) $(nand-y) diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index c4f2ace91ea2..3089d3bfa19b 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -270,6 +270,7 @@ extern const struct smp_operations omap4_smp_ops; extern int omap4_mpuss_init(void); extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); +extern u32 omap4_get_cpu1_ns_pa_addr(void); #else static inline int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c deleted file mode 100644 index f6ac027f3c3b..000000000000 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * gpmc-nand.c - * - * Copyright (C) 2009 Texas Instruments - * Vimal Singh <vimalsingh@ti.com> - * - * 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/kernel.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/omap-gpmc.h> -#include <linux/mtd/nand.h> -#include <linux/platform_data/mtd-nand-omap2.h> - -#include <asm/mach/flash.h> - -#include "soc.h" - -/* minimum size for IO mapping */ -#define NAND_IO_SIZE 4 - -static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) -{ - /* platforms which support all ECC schemes */ - if (soc_is_am33xx() || soc_is_am43xx() || cpu_is_omap44xx() || - soc_is_omap54xx() || soc_is_dra7xx()) - return 1; - - if (ecc_opt == OMAP_ECC_BCH4_CODE_HW_DETECTION_SW || - ecc_opt == OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) { - if (cpu_is_omap24xx()) - return 0; - else if (cpu_is_omap3630() && (GET_OMAP_REVISION() == 0)) - return 0; - else - return 1; - } - - /* OMAP3xxx do not have ELM engine, so cannot support ECC schemes - * which require H/W based ECC error detection */ - if ((cpu_is_omap34xx() || cpu_is_omap3630()) && - ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (ecc_opt == OMAP_ECC_BCH8_CODE_HW))) - return 0; - - /* legacy platforms support only HAM1 (1-bit Hamming) ECC scheme */ - if (ecc_opt == OMAP_ECC_HAM1_CODE_HW || - ecc_opt == OMAP_ECC_HAM1_CODE_SW) - return 1; - else - return 0; -} - -/* This function will go away once the device-tree convertion is complete */ -static void gpmc_set_legacy(struct omap_nand_platform_data *gpmc_nand_data, - struct gpmc_settings *s) -{ - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data->dev_ready) { - s->wait_on_read = true; - s->wait_on_write = true; - } - - if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) - s->device_width = GPMC_DEVWIDTH_16BIT; - else - s->device_width = GPMC_DEVWIDTH_8BIT; -} - -int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, - struct gpmc_timings *gpmc_t) -{ - int err = 0; - struct gpmc_settings s; - struct platform_device *pdev; - struct resource gpmc_nand_res[] = { - { .flags = IORESOURCE_MEM, }, - { .flags = IORESOURCE_IRQ, }, - { .flags = IORESOURCE_IRQ, }, - }; - - BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM); - - err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, - (unsigned long *)&gpmc_nand_res[0].start); - if (err < 0) { - pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n", - gpmc_nand_data->cs, err); - return err; - } - gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1; - gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); - gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); - - memset(&s, 0, sizeof(struct gpmc_settings)); - gpmc_set_legacy(gpmc_nand_data, &s); - - s.device_nand = true; - - if (gpmc_t) { - err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t, &s); - if (err < 0) { - pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", - err); - return err; - } - } - - err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s); - if (err < 0) - goto out_free_cs; - - err = gpmc_configure(GPMC_CONFIG_WP, 0); - if (err < 0) - goto out_free_cs; - - if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) { - pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n"); - err = -EINVAL; - goto out_free_cs; - } - - - pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs); - if (pdev) { - err = platform_device_add_resources(pdev, gpmc_nand_res, - ARRAY_SIZE(gpmc_nand_res)); - if (!err) - pdev->dev.platform_data = gpmc_nand_data; - } else { - err = -ENOMEM; - } - if (err) - goto out_free_pdev; - - err = platform_device_add(pdev); - if (err) { - dev_err(&pdev->dev, "Unable to register NAND device\n"); - goto out_free_pdev; - } - - return 0; - -out_free_pdev: - platform_device_put(pdev); -out_free_cs: - gpmc_cs_free(gpmc_nand_data->cs); - - return err; -} diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8633c703546a..2944af820558 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -367,7 +367,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) return ret; } -void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) +int gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) { int err; struct device *dev = &gpmc_onenand_device.dev; @@ -393,15 +393,17 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) if (err < 0) { dev_err(dev, "Cannot request GPMC CS %d, error %d\n", gpmc_onenand_data->cs, err); - return; + return err; } gpmc_onenand_resource.end = gpmc_onenand_resource.start + ONENAND_IO_SIZE - 1; - if (platform_device_register(&gpmc_onenand_device) < 0) { + err = platform_device_register(&gpmc_onenand_device); + if (err) { dev_err(dev, "Unable to register OneNAND device\n"); gpmc_cs_free(gpmc_onenand_data->cs); - return; } + + return err; } diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index fe36ce2734d4..4c6f14cf92a8 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -17,6 +17,7 @@ #include <linux/linkage.h> #include <linux/init.h> +#include <asm/assembler.h> #include "omap44xx.h" @@ -66,7 +67,7 @@ wait_2: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0 cmp r0, r4 bne wait_2 ldr r12, =API_HYP_ENTRY - adr r0, hyp_boot + badr r0, hyp_boot smc #0 hyp_boot: b omap_secondary_startup diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index d3fb5661bb5d..433db6d0b073 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c @@ -50,7 +50,7 @@ void omap4_cpu_die(unsigned int cpu) omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF); if (omap_secure_apis_support()) - boot_cpu = omap_read_auxcoreboot0(); + boot_cpu = omap_read_auxcoreboot0() >> 9; else boot_cpu = readl_relaxed(base + OMAP_AUX_CORE_BOOT_0) >> 5; diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 113ab2dd2ee9..03ec6d307c82 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -64,6 +64,7 @@ #include "prm-regbits-44xx.h" static void __iomem *sar_base; +static u32 old_cpu1_ns_pa_addr; #if defined(CONFIG_PM) && defined(CONFIG_SMP) @@ -212,6 +213,11 @@ static void __init save_l2x0_context(void) {} #endif +u32 omap4_get_cpu1_ns_pa_addr(void) +{ + return old_cpu1_ns_pa_addr; +} + /** * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function * The purpose of this function is to manage low power programming @@ -460,22 +466,30 @@ int __init omap4_mpuss_init(void) void __init omap4_mpuss_early_init(void) { unsigned long startup_pa; + void __iomem *ns_pa_addr; - if (!(cpu_is_omap44xx() || soc_is_omap54xx())) + if (!(soc_is_omap44xx() || soc_is_omap54xx())) return; sar_base = omap4_get_sar_ram_base(); - if (cpu_is_omap443x()) + /* Save old NS_PA_ADDR for validity checks later on */ + if (soc_is_omap44xx()) + ns_pa_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + else + ns_pa_addr = sar_base + OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + old_cpu1_ns_pa_addr = readl_relaxed(ns_pa_addr); + + if (soc_is_omap443x()) startup_pa = __pa_symbol(omap4_secondary_startup); - else if (cpu_is_omap446x()) + else if (soc_is_omap446x()) startup_pa = __pa_symbol(omap4460_secondary_startup); else if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE) startup_pa = __pa_symbol(omap5_secondary_hyp_startup); else startup_pa = __pa_symbol(omap5_secondary_startup); - if (cpu_is_omap44xx()) + if (soc_is_omap44xx()) writel_relaxed(startup_pa, sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET); else diff --git a/arch/arm/mach-omap2/omap-smc.S b/arch/arm/mach-omap2/omap-smc.S index fd90125bffc7..72506e6cf9e7 100644 --- a/arch/arm/mach-omap2/omap-smc.S +++ b/arch/arm/mach-omap2/omap-smc.S @@ -94,6 +94,5 @@ ENTRY(omap_read_auxcoreboot0) ldr r12, =0x103 dsb smc #0 - mov r0, r0, lsr #9 ldmfd sp!, {r2-r12, pc} ENDPROC(omap_read_auxcoreboot0) diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 003353b0b794..3faf454ba487 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <linux/irqchip/arm-gic.h> +#include <asm/sections.h> #include <asm/smp_scu.h> #include <asm/virt.h> @@ -40,10 +41,14 @@ #define OMAP5_CORE_COUNT 0x2 +#define AUX_CORE_BOOT0_GP_RELEASE 0x020 +#define AUX_CORE_BOOT0_HS_RELEASE 0x200 + struct omap_smp_config { unsigned long cpu1_rstctrl_pa; void __iomem *cpu1_rstctrl_va; void __iomem *scu_base; + void __iomem *wakeupgen_base; void *startup_addr; }; @@ -140,7 +145,6 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) static struct clockdomain *cpu1_clkdm; static bool booted; static struct powerdomain *cpu1_pwrdm; - void __iomem *base = omap_get_wakeupgen_base(); /* * Set synchronisation state between this boot processor @@ -155,9 +159,11 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) * A barrier is added to ensure that write buffer is drained */ if (omap_secure_apis_support()) - omap_modify_auxcoreboot0(0x200, 0xfffffdff); + omap_modify_auxcoreboot0(AUX_CORE_BOOT0_HS_RELEASE, + 0xfffffdff); else - writel_relaxed(0x20, base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(AUX_CORE_BOOT0_GP_RELEASE, + cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_0); if (!cpu1_clkdm && !cpu1_pwrdm) { cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); @@ -261,9 +267,72 @@ static void __init omap4_smp_init_cpus(void) set_cpu_possible(i, true); } +/* + * For now, just make sure the start-up address is not within the booting + * kernel space as that means we just overwrote whatever secondary_startup() + * code there was. + */ +static bool __init omap4_smp_cpu1_startup_valid(unsigned long addr) +{ + if ((addr >= __pa(PAGE_OFFSET)) && (addr <= __pa(__bss_start))) + return false; + + return true; +} + +/* + * We may need to reset CPU1 before configuring, otherwise kexec boot can end + * up trying to use old kernel startup address or suspend-resume will + * occasionally fail to bring up CPU1 on 4430 if CPU1 fails to enter deeper + * idle states. + */ +static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c) +{ + unsigned long cpu1_startup_pa, cpu1_ns_pa_addr; + bool needs_reset = false; + u32 released; + + if (omap_secure_apis_support()) + released = omap_read_auxcoreboot0() & AUX_CORE_BOOT0_HS_RELEASE; + else + released = readl_relaxed(cfg.wakeupgen_base + + OMAP_AUX_CORE_BOOT_0) & + AUX_CORE_BOOT0_GP_RELEASE; + if (released) { + pr_warn("smp: CPU1 not parked?\n"); + + return; + } + + cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base + + OMAP_AUX_CORE_BOOT_1); + cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr(); + + /* Did the configured secondary_startup() get overwritten? */ + if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa)) + needs_reset = true; + + /* + * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a + * deeper idle state in WFI and will wake to an invalid address. + */ + if ((soc_is_omap44xx() || soc_is_omap54xx()) && + !omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr)) + needs_reset = true; + + if (!needs_reset || !c->cpu1_rstctrl_va) + return; + + pr_info("smp: CPU1 parked within kernel, needs reset (0x%lx 0x%lx)\n", + cpu1_startup_pa, cpu1_ns_pa_addr); + + writel_relaxed(1, c->cpu1_rstctrl_va); + readl_relaxed(c->cpu1_rstctrl_va); + writel_relaxed(0, c->cpu1_rstctrl_va); +} + static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) { - void __iomem *base = omap_get_wakeupgen_base(); const struct omap_smp_config *c = NULL; if (soc_is_omap443x()) @@ -281,6 +350,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) /* Must preserve cfg.scu_base set earlier */ cfg.cpu1_rstctrl_pa = c->cpu1_rstctrl_pa; cfg.startup_addr = c->startup_addr; + cfg.wakeupgen_base = omap_get_wakeupgen_base(); if (soc_is_dra74x() || soc_is_omap54xx()) { if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE) @@ -299,15 +369,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) if (cfg.scu_base) scu_enable(cfg.scu_base); - /* - * Reset CPU1 before configuring, otherwise kexec will - * end up trying to use old kernel startup address. - */ - if (cfg.cpu1_rstctrl_va) { - writel_relaxed(1, cfg.cpu1_rstctrl_va); - readl_relaxed(cfg.cpu1_rstctrl_va); - writel_relaxed(0, cfg.cpu1_rstctrl_va); - } + omap4_smp_maybe_reset_cpu1(&cfg); /* * Write the address of secondary startup routine into the @@ -319,7 +381,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) omap_auxcoreboot_addr(__pa_symbol(cfg.startup_addr)); else writel_relaxed(__pa_symbol(cfg.startup_addr), - base + OMAP_AUX_CORE_BOOT_1); + cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_1); } const struct smp_operations omap4_smp_ops __initconst = { diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index e920dd83e443..f989145480c8 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -222,6 +222,14 @@ static int _omap_device_notifier_call(struct notifier_block *nb, dev_err(dev, "failed to idle\n"); } break; + case BUS_NOTIFY_BIND_DRIVER: + od = to_omap_device(pdev); + if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && + pm_runtime_status_suspended(dev)) { + od->_driver_status = BUS_NOTIFY_BIND_DRIVER; + pm_runtime_set_active(dev); + } + break; case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev); diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 56f917ec8621..1435fee39a89 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -2112,11 +2112,20 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = { }; /* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = { + { + .pa_start = OMAP34XX_SR1_BASE, + .pa_end = OMAP34XX_SR1_BASE + SZ_1K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; static struct omap_hwmod_ocp_if omap34xx_l4_core__sr1 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap34xx_sr1_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr1_addr_space, .user = OCP_USER_MPU, }; @@ -2124,15 +2133,25 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr1 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap36xx_sr1_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr1_addr_space, .user = OCP_USER_MPU, }; /* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = { + { + .pa_start = OMAP34XX_SR2_BASE, + .pa_end = OMAP34XX_SR2_BASE + SZ_1K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; static struct omap_hwmod_ocp_if omap34xx_l4_core__sr2 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap34xx_sr2_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr2_addr_space, .user = OCP_USER_MPU, }; @@ -2140,6 +2159,7 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr2 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap36xx_sr2_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr2_addr_space, .user = OCP_USER_MPU, }; @@ -3111,16 +3131,20 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_hwmod_ocp_ifs[] __initdata = { * Return: 0 if device named @dev_name is not likely to be accessible, * or 1 if it is likely to be accessible. */ -static int __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus, - const char *dev_name) +static bool __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus, + const char *dev_name) { + struct device_node *node; + bool available; + if (!bus) - return (omap_type() == OMAP2_DEVICE_TYPE_GP) ? 1 : 0; + return omap_type() == OMAP2_DEVICE_TYPE_GP; - if (of_device_is_available(of_find_node_by_name(bus, dev_name))) - return 1; + node = of_get_child_by_name(bus, dev_name); + available = of_device_is_available(node); + of_node_put(node); - return 0; + return available; } int __init omap3xxx_hwmod_init(void) @@ -3189,15 +3213,20 @@ int __init omap3xxx_hwmod_init(void) if (h_sham && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "sham")) { r = omap_hwmod_register_links(h_sham); - if (r < 0) + if (r < 0) { + of_node_put(bus); return r; + } } if (h_aes && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "aes")) { r = omap_hwmod_register_links(h_aes); - if (r < 0) + if (r < 0) { + of_node_put(bus); return r; + } } + of_node_put(bus); /* * Register hwmod links specific to certain ES levels of a diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index 633442ad4e4c..2a7bb6ccdcb7 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig @@ -6,6 +6,7 @@ menuconfig ARCH_ORION5X select GPIOLIB select MVEBU_MBUS select PCI + select PHYLIB if NETDEVICES select PLAT_ORION_LEGACY help Support for the following Marvell Orion 5x series SoCs: diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 63eabb06f9f1..475811f5383a 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -935,13 +935,31 @@ static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_add __arm_dma_free(dev, size, cpu_addr, handle, attrs, true); } +/* + * The whole dma_get_sgtable() idea is fundamentally unsafe - it seems + * that the intention is to allow exporting memory allocated via the + * coherent DMA APIs through the dma_buf API, which only accepts a + * scattertable. This presents a couple of problems: + * 1. Not all memory allocated via the coherent DMA APIs is backed by + * a struct page + * 2. Passing coherent DMA memory into the streaming APIs is not allowed + * as we will try to flush the memory through a different alias to that + * actually being used (and the flushes are redundant.) + */ int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt, void *cpu_addr, dma_addr_t handle, size_t size, unsigned long attrs) { - struct page *page = pfn_to_page(dma_to_pfn(dev, handle)); + unsigned long pfn = dma_to_pfn(dev, handle); + struct page *page; int ret; + /* If the PFN is not valid, we do not have a struct page */ + if (!pfn_valid(pfn)) + return -ENXIO; + + page = pfn_to_page(pfn); + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); if (unlikely(ret)) return ret; diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 3b5c7aaf9c76..33a45bd96860 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -303,7 +303,10 @@ static inline void set_vbar(unsigned long val) */ static inline bool security_extensions_enabled(void) { - return !!cpuid_feature_extract(CPUID_EXT_PFR1, 4); + /* Check CPUID Identification Scheme before ID_PFR1 read */ + if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) + return !!cpuid_feature_extract(CPUID_EXT_PFR1, 4); + return 0; } static unsigned long __init setup_vectors_base(void) diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c index 9255b6d67ba5..aff6994950ba 100644 --- a/arch/arm/plat-orion/common.c +++ b/arch/arm/plat-orion/common.c @@ -468,6 +468,7 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data, eth_data, &orion_ge11); } +#ifdef CONFIG_ARCH_ORION5X /***************************************************************************** * Ethernet switch ****************************************************************************/ @@ -480,6 +481,9 @@ void __init orion_ge00_switch_init(struct dsa_chip_data *d) struct mdio_board_info *bd; unsigned int i; + if (!IS_BUILTIN(CONFIG_PHYLIB)) + return; + for (i = 0; i < ARRAY_SIZE(d->port_names); i++) if (!strcmp(d->port_names[i], "cpu")) break; @@ -493,6 +497,7 @@ void __init orion_ge00_switch_init(struct dsa_chip_data *d) mdiobus_register_board_info(&orion_ge00_switch_board_info, 1); } +#endif /***************************************************************************** * I2C diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index b6dc9d838a9a..ad1f4e6a9e33 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -266,11 +266,20 @@ void __kprobes kprobe_handler(struct pt_regs *regs) #endif if (p) { - if (cur) { + if (!p->ainsn.insn_check_cc(regs->ARM_cpsr)) { + /* + * Probe hit but conditional execution check failed, + * so just skip the instruction and continue as if + * nothing had happened. + * In this case, we can skip recursing check too. + */ + singlestep_skip(p, regs); + } else if (cur) { /* Kprobe is pending, so we're recursing. */ switch (kcb->kprobe_status) { case KPROBE_HIT_ACTIVE: case KPROBE_HIT_SSDONE: + case KPROBE_HIT_SS: /* A pre- or post-handler probe got us here. */ kprobes_inc_nmissed_count(p); save_previous_kprobe(kcb); @@ -279,11 +288,16 @@ void __kprobes kprobe_handler(struct pt_regs *regs) singlestep(p, regs, kcb); restore_previous_kprobe(kcb); break; + case KPROBE_REENTER: + /* A nested probe was hit in FIQ, it is a BUG */ + pr_warn("Unrecoverable kprobe detected at %p.\n", + p->addr); + /* fall through */ default: /* impossible cases */ BUG(); } - } else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) { + } else { /* Probe hit and conditional execution check ok. */ set_current_kprobe(p); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -304,13 +318,6 @@ void __kprobes kprobe_handler(struct pt_regs *regs) } reset_current_kprobe(); } - } else { - /* - * Probe hit but conditional execution check failed, - * so just skip the instruction and continue as if - * nothing had happened. - */ - singlestep_skip(p, regs); } } else if (cur) { /* We probably hit a jprobe. Call its break handler. */ @@ -434,6 +441,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) struct hlist_node *tmp; unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; + kprobe_opcode_t *correct_ret_addr = NULL; INIT_HLIST_HEAD(&empty_rp); kretprobe_hash_lock(current, &head, &flags); @@ -456,14 +464,34 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) /* another task is sharing our hash bucket */ continue; + orig_ret_address = (unsigned long)ri->ret_addr; + + if (orig_ret_address != trampoline_address) + /* + * This is the real return address. Any other + * instances associated with this task are for + * other calls deeper on the call stack + */ + break; + } + + kretprobe_assert(ri, orig_ret_address, trampoline_address); + + correct_ret_addr = ri->ret_addr; + hlist_for_each_entry_safe(ri, tmp, head, hlist) { + if (ri->task != current) + /* another task is sharing our hash bucket */ + continue; + + orig_ret_address = (unsigned long)ri->ret_addr; if (ri->rp && ri->rp->handler) { __this_cpu_write(current_kprobe, &ri->rp->kp); get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; + ri->ret_addr = correct_ret_addr; ri->rp->handler(ri, regs); __this_cpu_write(current_kprobe, NULL); } - orig_ret_address = (unsigned long)ri->ret_addr; recycle_rp_inst(ri, &empty_rp); if (orig_ret_address != trampoline_address) @@ -475,7 +503,6 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) break; } - kretprobe_assert(ri, orig_ret_address, trampoline_address); kretprobe_hash_unlock(current, &flags); hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index c893726aa52d..1c98a87786ca 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -977,7 +977,10 @@ static void coverage_end(void) void __naked __kprobes_test_case_start(void) { __asm__ __volatile__ ( - "stmdb sp!, {r4-r11} \n\t" + "mov r2, sp \n\t" + "bic r3, r2, #7 \n\t" + "mov sp, r3 \n\t" + "stmdb sp!, {r2-r11} \n\t" "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" "bic r0, lr, #1 @ r0 = inline data \n\t" "mov r1, sp \n\t" @@ -997,7 +1000,8 @@ void __naked __kprobes_test_case_end_32(void) "movne pc, r0 \n\t" "mov r0, r4 \n\t" "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" - "ldmia sp!, {r4-r11} \n\t" + "ldmia sp!, {r2-r11} \n\t" + "mov sp, r2 \n\t" "mov pc, r0 \n\t" ); } @@ -1013,7 +1017,8 @@ void __naked __kprobes_test_case_end_16(void) "bxne r0 \n\t" "mov r0, r4 \n\t" "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" - "ldmia sp!, {r4-r11} \n\t" + "ldmia sp!, {r2-r11} \n\t" + "mov sp, r2 \n\t" "bx r0 \n\t" ); } diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 3c2cb5d5adfa..0bb0e9c6376c 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -411,3 +411,4 @@ 394 common pkey_mprotect sys_pkey_mprotect 395 common pkey_alloc sys_pkey_alloc 396 common pkey_free sys_pkey_free +397 common statx sys_statx diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c index ce18c91b50a1..f0325d96b97a 100644 --- a/arch/arm/xen/mm.c +++ b/arch/arm/xen/mm.c @@ -198,6 +198,8 @@ static const struct dma_map_ops xen_swiotlb_dma_ops = { .unmap_page = xen_swiotlb_unmap_page, .dma_supported = xen_swiotlb_dma_supported, .set_dma_mask = xen_swiotlb_set_dma_mask, + .mmap = xen_swiotlb_dma_mmap, + .get_sgtable = xen_swiotlb_get_sgtable, }; int __init xen_mm_init(void) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a39029b5414e..67695fadae96 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -2,6 +2,7 @@ config ARM64 def_bool y select ACPI_CCA_REQUIRED if ACPI select ACPI_GENERIC_GSI if ACPI + select ACPI_GTDT if ACPI select ACPI_REDUCED_HARDWARE_ONLY if ACPI select ACPI_MCFG if ACPI select ACPI_SPCR_TABLE if ACPI @@ -60,7 +61,6 @@ config ARM64 select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_BITREVERSE - select HAVE_ARCH_HARDENED_USERCOPY select HAVE_ARCH_HUGE_VMAP select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48) @@ -508,6 +508,16 @@ config QCOM_FALKOR_ERRATUM_1009 If unsure, say Y. +config QCOM_QDF2400_ERRATUM_0065 + bool "QDF2400 E0065: Incorrect GITS_TYPER.ITT_Entry_size" + default y + help + On Qualcomm Datacenter Technologies QDF2400 SoC, ITS hardware reports + ITE size incorrectly. The GITS_TYPER.ITT_Entry_size field should have + been indicated as 16Bytes (0xf), not 8Bytes (0x7). + + If unsure, say Y. + endmenu @@ -1063,6 +1073,10 @@ config SYSVIPC_COMPAT def_bool y depends on COMPAT && SYSVIPC +config KEYS_COMPAT + def_bool y + depends on COMPAT && KEYS + endmenu menu "Power management options" diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 1c64ea2d23f9..0565779e66fa 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -179,8 +179,10 @@ usbphy: phy@01c19400 { compatible = "allwinner,sun50i-a64-usb-phy"; reg = <0x01c19400 0x14>, + <0x01c1a800 0x4>, <0x01c1b800 0x4>; reg-names = "phy_ctrl", + "pmu0", "pmu1"; clocks = <&ccu CLK_USB_PHY0>, <&ccu CLK_USB_PHY1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi index 5d995f7724af..620495a43363 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi @@ -380,7 +380,7 @@ #size-cells = <2>; ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>; - rng { + hwrng: rng { compatible = "amlogic,meson-rng"; reg = <0x0 0x0 0x0 0x4>; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi index 04b3324bc132..a375cb21cc8b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi @@ -524,3 +524,8 @@ &vpu { compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu"; }; + +&hwrng { + clocks = <&clkc CLKID_RNG0>; + clock-names = "core"; +}; diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 9f9e203c09c5..bcb03fc32665 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -114,6 +114,7 @@ pcie0: pcie@20020000 { compatible = "brcm,iproc-pcie"; reg = <0 0x20020000 0 0x1000>; + dma-coherent; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; @@ -144,6 +145,7 @@ pcie4: pcie@50020000 { compatible = "brcm,iproc-pcie"; reg = <0 0x50020000 0 0x1000>; + dma-coherent; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; @@ -174,6 +176,7 @@ pcie8: pcie@60c00000 { compatible = "brcm,iproc-pcie-paxc"; reg = <0 0x60c00000 0 0x1000>; + dma-coherent; linux,pci-domain = <8>; bus-range = <0x0 0x1>; @@ -203,6 +206,7 @@ <0x61030000 0x100>; reg-names = "amac_base", "idm_base", "nicpm_base"; interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>; + dma-coherent; phy-handle = <&gphy0>; phy-mode = "rgmii"; status = "disabled"; @@ -213,6 +217,7 @@ reg = <0x612c0000 0x445>; /* PDC FS0 regs */ interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>; #mbox-cells = <1>; + dma-coherent; brcm,rx-status-len = <32>; brcm,use-bcm-hdr; }; @@ -222,6 +227,7 @@ reg = <0x612e0000 0x445>; /* PDC FS1 regs */ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; #mbox-cells = <1>; + dma-coherent; brcm,rx-status-len = <32>; brcm,use-bcm-hdr; }; @@ -231,6 +237,7 @@ reg = <0x61300000 0x445>; /* PDC FS2 regs */ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; #mbox-cells = <1>; + dma-coherent; brcm,rx-status-len = <32>; brcm,use-bcm-hdr; }; @@ -240,6 +247,7 @@ reg = <0x61320000 0x445>; /* PDC FS3 regs */ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; #mbox-cells = <1>; + dma-coherent; brcm,rx-status-len = <32>; brcm,use-bcm-hdr; }; @@ -644,6 +652,7 @@ sata: ahci@663f2000 { compatible = "brcm,iproc-ahci", "generic-ahci"; reg = <0x663f2000 0x1000>; + dma-coherent; reg-names = "ahci"; interrupts = <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -667,6 +676,7 @@ compatible = "brcm,sdhci-iproc-cygnus"; reg = <0x66420000 0x100>; interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>; + dma-coherent; bus-width = <8>; clocks = <&genpll_sw BCM_NS2_GENPLL_SW_SDIO_CLK>; status = "disabled"; @@ -676,6 +686,7 @@ compatible = "brcm,sdhci-iproc-cygnus"; reg = <0x66430000 0x100>; interrupts = <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>; + dma-coherent; bus-width = <8>; clocks = <&genpll_sw BCM_NS2_GENPLL_SW_SDIO_CLK>; status = "disabled"; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index dba3c131c62c..9b4ba7169210 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -98,6 +98,11 @@ assigned-clocks = <&sys_ctrl HI6220_UART1_SRC>; assigned-clock-rates = <150000000>; status = "ok"; + + bluetooth { + compatible = "ti,wl1835-st"; + enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + }; }; uart2: uart@f7112000 { diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index a749ba2edec4..5019c8f4acd0 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -235,7 +235,8 @@ #clock-cells = <1>; clock-output-names = "ap-cpu-cluster-0", "ap-cpu-cluster-1", - "ap-fixed", "ap-mss"; + "ap-fixed", "ap-mss", + "ap-emmc"; reg = <0x6f4000 0x1000>; }; }; diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index b4b34004a21e..74d08e44a651 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -25,6 +25,7 @@ #include <linux/bug.h> #include <linux/init.h> #include <linux/jump_label.h> +#include <linux/smp.h> #include <linux/types.h> #include <clocksource/arm_arch_timer.h> @@ -37,24 +38,44 @@ extern struct static_key_false arch_timer_read_ool_enabled; #define needs_unstable_timer_counter_workaround() false #endif +enum arch_timer_erratum_match_type { + ate_match_dt, + ate_match_local_cap_id, + ate_match_acpi_oem_info, +}; + +struct clock_event_device; struct arch_timer_erratum_workaround { - const char *id; /* Indicate the Erratum ID */ + enum arch_timer_erratum_match_type match_type; + const void *id; + const char *desc; u32 (*read_cntp_tval_el0)(void); u32 (*read_cntv_tval_el0)(void); u64 (*read_cntvct_el0)(void); + int (*set_next_event_phys)(unsigned long, struct clock_event_device *); + int (*set_next_event_virt)(unsigned long, struct clock_event_device *); }; -extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround; - -#define arch_timer_reg_read_stable(reg) \ -({ \ - u64 _val; \ - if (needs_unstable_timer_counter_workaround()) \ - _val = timer_unstable_counter_workaround->read_##reg();\ - else \ - _val = read_sysreg(reg); \ - _val; \ +DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *, + timer_unstable_counter_workaround); + +#define arch_timer_reg_read_stable(reg) \ +({ \ + u64 _val; \ + if (needs_unstable_timer_counter_workaround()) { \ + const struct arch_timer_erratum_workaround *wa; \ + preempt_disable(); \ + wa = __this_cpu_read(timer_unstable_counter_workaround); \ + if (wa && wa->read_##reg) \ + _val = wa->read_##reg(); \ + else \ + _val = read_sysreg(reg); \ + preempt_enable(); \ + } else { \ + _val = read_sysreg(reg); \ + } \ + _val; \ }) /* diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h index 561190d15881..a9be1072933c 100644 --- a/arch/arm64/include/asm/bug.h +++ b/arch/arm64/include/asm/bug.h @@ -55,7 +55,7 @@ _BUGVERBOSE_LOCATION(__FILE__, __LINE__) \ unreachable(); \ } while (0) -#define __WARN_TAINT(taint) _BUG_FLAGS(BUGFLAG_TAINT(taint)) +#define __WARN_FLAGS(flags) _BUG_FLAGS(BUGFLAG_WARNING|(flags)) #endif /* ! CONFIG_GENERIC_BUG */ diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index fb78a5d3b60b..b3aab8a17868 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -37,7 +37,8 @@ #define ARM64_HAS_NO_FPSIMD 16 #define ARM64_WORKAROUND_REPEAT_TLBI 17 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18 +#define ARM64_WORKAROUND_858921 19 -#define ARM64_NCAPS 19 +#define ARM64_NCAPS 20 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 05310ad8c5ab..f31c48d0cd68 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -251,7 +251,7 @@ static inline bool system_supports_fpsimd(void) static inline bool system_uses_ttbr0_pan(void) { return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) && - !cpus_have_cap(ARM64_HAS_PAN); + !cpus_have_const_cap(ARM64_HAS_PAN); } #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index fc502713ab37..0984d1b3a8f2 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -80,6 +80,7 @@ #define ARM_CPU_PART_FOUNDATION 0xD00 #define ARM_CPU_PART_CORTEX_A57 0xD07 #define ARM_CPU_PART_CORTEX_A53 0xD03 +#define ARM_CPU_PART_CORTEX_A73 0xD09 #define APM_CPU_PART_POTENZA 0x000 @@ -92,6 +93,7 @@ #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) +#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1) diff --git a/arch/arm64/include/asm/current.h b/arch/arm64/include/asm/current.h index 86c404171305..f6580d4afb0e 100644 --- a/arch/arm64/include/asm/current.h +++ b/arch/arm64/include/asm/current.h @@ -3,8 +3,6 @@ #include <linux/compiler.h> -#include <asm/sysreg.h> - #ifndef __ASSEMBLY__ struct task_struct; diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index e7445281e534..8f3043aba873 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -1,6 +1,7 @@ #ifndef _ASM_EFI_H #define _ASM_EFI_H +#include <asm/boot.h> #include <asm/cpufeature.h> #include <asm/io.h> #include <asm/mmu_context.h> @@ -46,7 +47,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); * 2MiB so we know it won't cross a 2MiB boundary. */ #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ -#define MAX_FDT_OFFSET SZ_512M + +/* on arm64, the FDT may be located anywhere in system RAM */ +static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) +{ + return ULONG_MAX; +} + +/* + * On arm64, we have to ensure that the initrd ends up in the linear region, + * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is + * guaranteed to cover the kernel Image. + * + * Since the EFI stub is part of the kernel Image, we can relax the + * usual requirements in Documentation/arm64/booting.txt, which still + * apply to other bootloaders, and are required for some kernel + * configurations. + */ +static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, + unsigned long image_addr) +{ + return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1)); +} #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) #define __efi_call_early(f, ...) f(__VA_ARGS__) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index d14c478976d0..ad42e79a5d4d 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -175,6 +175,8 @@ #define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \ ESR_ELx_SYS64_ISS_DIR_READ) +#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) #ifndef __ASSEMBLY__ #include <asm/types.h> diff --git a/arch/arm64/include/asm/extable.h b/arch/arm64/include/asm/extable.h new file mode 100644 index 000000000000..42f50f15a44c --- /dev/null +++ b/arch/arm64/include/asm/extable.h @@ -0,0 +1,25 @@ +#ifndef __ASM_EXTABLE_H +#define __ASM_EXTABLE_H + +/* + * The exception table consists of pairs of relative offsets: the first + * is the relative offset to an instruction that is allowed to fault, + * and the second is the relative offset 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 +{ + int insn, fixup; +}; + +#define ARCH_HAS_RELATIVE_EXTABLE + +extern int fixup_exception(struct pt_regs *regs); +#endif diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index aecc07e09a18..29cb2ca756f6 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -80,6 +80,7 @@ enum aarch64_insn_register_type { AARCH64_INSN_REGTYPE_RM, AARCH64_INSN_REGTYPE_RD, AARCH64_INSN_REGTYPE_RA, + AARCH64_INSN_REGTYPE_RS, }; enum aarch64_insn_register { @@ -188,6 +189,8 @@ enum aarch64_insn_ldst_type { AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX, AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX, AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX, + AARCH64_INSN_LDST_LOAD_EX, + AARCH64_INSN_LDST_STORE_EX, }; enum aarch64_insn_adsb_type { @@ -240,6 +243,23 @@ enum aarch64_insn_logic_type { AARCH64_INSN_LOGIC_BIC_SETFLAGS }; +enum aarch64_insn_prfm_type { + AARCH64_INSN_PRFM_TYPE_PLD, + AARCH64_INSN_PRFM_TYPE_PLI, + AARCH64_INSN_PRFM_TYPE_PST, +}; + +enum aarch64_insn_prfm_target { + AARCH64_INSN_PRFM_TARGET_L1, + AARCH64_INSN_PRFM_TARGET_L2, + AARCH64_INSN_PRFM_TARGET_L3, +}; + +enum aarch64_insn_prfm_policy { + AARCH64_INSN_PRFM_POLICY_KEEP, + AARCH64_INSN_PRFM_POLICY_STRM, +}; + #define __AARCH64_INSN_FUNCS(abbr, mask, val) \ static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ { return (code & (mask)) == (val); } \ @@ -248,6 +268,7 @@ static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ __AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000) __AARCH64_INSN_FUNCS(adrp, 0x9F000000, 0x90000000) +__AARCH64_INSN_FUNCS(prfm, 0x3FC00000, 0x39800000) __AARCH64_INSN_FUNCS(prfm_lit, 0xFF000000, 0xD8000000) __AARCH64_INSN_FUNCS(str_reg, 0x3FE0EC00, 0x38206800) __AARCH64_INSN_FUNCS(ldr_reg, 0x3FE0EC00, 0x38606800) @@ -357,6 +378,11 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, int offset, enum aarch64_insn_variant variant, enum aarch64_insn_ldst_type type); +u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg, + enum aarch64_insn_register base, + enum aarch64_insn_register state, + enum aarch64_insn_size_type size, + enum aarch64_insn_ldst_type type); u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, enum aarch64_insn_register src, int imm, enum aarch64_insn_variant variant, @@ -397,6 +423,10 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, int shift, enum aarch64_insn_variant variant, enum aarch64_insn_logic_type type); +u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base, + enum aarch64_insn_prfm_type type, + enum aarch64_insn_prfm_target target, + enum aarch64_insn_prfm_policy policy); s32 aarch64_get_branch_offset(u32 insn); u32 aarch64_set_branch_offset(u32 insn, s32 offset); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index f21fd3894370..e7705e7bb07b 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -30,8 +30,7 @@ #define __KVM_HAVE_ARCH_INTC_INITIALIZED -#define KVM_USER_MEM_SLOTS 32 -#define KVM_PRIVATE_MEM_SLOTS 4 +#define KVM_USER_MEM_SLOTS 512 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HALT_POLL_NS_DEFAULT 500000 diff --git a/arch/arm64/include/asm/pgtable-types.h b/arch/arm64/include/asm/pgtable-types.h index 69b2fd41503c..345a072b5856 100644 --- a/arch/arm64/include/asm/pgtable-types.h +++ b/arch/arm64/include/asm/pgtable-types.h @@ -55,9 +55,13 @@ typedef struct { pteval_t pgprot; } pgprot_t; #define __pgprot(x) ((pgprot_t) { (x) } ) #if CONFIG_PGTABLE_LEVELS == 2 +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #elif CONFIG_PGTABLE_LEVELS == 3 +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> +#elif CONFIG_PGTABLE_LEVELS == 4 +#include <asm-generic/5level-fixup.h> #endif #endif /* __ASM_PGTABLE_TYPES_H */ diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 5308d696311b..ba497172610d 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -28,38 +28,12 @@ #include <linux/bitops.h> #include <linux/kasan-checks.h> #include <linux/string.h> -#include <linux/thread_info.h> #include <asm/cpufeature.h> #include <asm/ptrace.h> -#include <asm/errno.h> #include <asm/memory.h> #include <asm/compiler.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The exception table consists of pairs of relative offsets: the first - * is the relative offset to an instruction that is allowed to fault, - * and the second is the relative offset 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 -{ - int insn, fixup; -}; - -#define ARCH_HAS_RELATIVE_EXTABLE - -extern int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> #define KERNEL_DS (-1UL) #define get_ds() (KERNEL_DS) @@ -357,58 +331,13 @@ do { \ }) extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n); +#define raw_copy_from_user __arch_copy_from_user extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n); -extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n); +#define raw_copy_to_user __arch_copy_to_user +extern unsigned long __must_check raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); - -static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n) -{ - kasan_check_write(to, n); - check_object_size(to, n, false); - return __arch_copy_from_user(to, from, n); -} - -static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) -{ - kasan_check_read(from, n); - check_object_size(from, n, true); - return __arch_copy_to_user(to, from, n); -} - -static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) -{ - unsigned long res = n; - kasan_check_write(to, n); - check_object_size(to, n, false); - - if (access_ok(VERIFY_READ, from, n)) { - res = __arch_copy_from_user(to, from, n); - } - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; -} - -static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) -{ - kasan_check_read(from, n); - check_object_size(from, n, true); - - if (access_ok(VERIFY_WRITE, to, n)) { - n = __arch_copy_to_user(to, from, n); - } - return n; -} - -static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n) -{ - if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)) - n = __copy_in_user(to, from, n); - return n; -} - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#define INLINE_COPY_TO_USER +#define INLINE_COPY_FROM_USER static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) { diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index e78ac26324bd..a0baa9af5487 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -14,7 +14,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef CONFIG_COMPAT -#define __ARCH_WANT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE @@ -44,7 +43,7 @@ #define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2) #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5) -#define __NR_compat_syscalls 394 +#define __NR_compat_syscalls 398 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index b7e8ef16ff0d..ef292160748c 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -456,7 +456,7 @@ __SYSCALL(__NR_setfsuid32, sys_setfsuid) #define __NR_setfsgid32 216 __SYSCALL(__NR_setfsgid32, sys_setfsgid) #define __NR_getdents64 217 -__SYSCALL(__NR_getdents64, compat_sys_getdents64) +__SYSCALL(__NR_getdents64, sys_getdents64) #define __NR_pivot_root 218 __SYSCALL(__NR_pivot_root, sys_pivot_root) #define __NR_mincore 219 @@ -809,6 +809,14 @@ __SYSCALL(__NR_copy_file_range, sys_copy_file_range) __SYSCALL(__NR_preadv2, compat_sys_preadv2) #define __NR_pwritev2 393 __SYSCALL(__NR_pwritev2, compat_sys_pwritev2) +#define __NR_pkey_mprotect 394 +__SYSCALL(__NR_pkey_mprotect, sys_pkey_mprotect) +#define __NR_pkey_alloc 395 +__SYSCALL(__NR_pkey_alloc, sys_pkey_alloc) +#define __NR_pkey_free 396 +__SYSCALL(__NR_pkey_free, sys_pkey_free) +#define __NR_statx 397 +__SYSCALL(__NR_statx, sys_statx) /* * Please add new compat syscalls above this comment and update diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 64d9cbd61678..e25c11e727fe 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -18,6 +18,7 @@ #include <linux/acpi.h> #include <linux/bootmem.h> #include <linux/cpumask.h> +#include <linux/efi-bgrt.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/irqdomain.h> @@ -233,6 +234,8 @@ done: early_init_dt_scan_chosen_stdout(); } else { parse_spcr(earlycon_init_is_deferred); + if (IS_ENABLED(CONFIG_ACPI_BGRT)) + acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); } } diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index e9c4dc9e0ada..67368c7329c0 100644 --- a/arch/arm64/kernel/arm64ksyms.c +++ b/arch/arm64/kernel/arm64ksyms.c @@ -38,7 +38,7 @@ EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__arch_copy_from_user); EXPORT_SYMBOL(__arch_copy_to_user); EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(__copy_in_user); +EXPORT_SYMBOL(raw_copy_in_user); /* physical memory */ EXPORT_SYMBOL(memstart_addr); diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f6cc67e7626e..2ed2a7657711 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -53,6 +53,13 @@ static int cpu_enable_trap_ctr_access(void *__unused) .midr_range_min = min, \ .midr_range_max = max +#define MIDR_ALL_VERSIONS(model) \ + .def_scope = SCOPE_LOCAL_CPU, \ + .matches = is_affected_midr_range, \ + .midr_model = model, \ + .midr_range_min = 0, \ + .midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK) + const struct arm64_cpu_capabilities arm64_errata[] = { #if defined(CONFIG_ARM64_ERRATUM_826319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \ @@ -151,6 +158,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { MIDR_CPU_VAR_REV(0, 0)), }, #endif +#ifdef CONFIG_ARM64_ERRATUM_858921 + { + /* Cortex-A73 all versions */ + .desc = "ARM erratum 858921", + .capability = ARM64_WORKAROUND_858921, + MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), + }, +#endif { } }; diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index abda8e861865..6eb77ae99b79 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1090,20 +1090,29 @@ static void __init setup_feature_capabilities(void) * Check if the current CPU has a given feature capability. * Should be called from non-preemptible context. */ -bool this_cpu_has_cap(unsigned int cap) +static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array, + unsigned int cap) { const struct arm64_cpu_capabilities *caps; if (WARN_ON(preemptible())) return false; - for (caps = arm64_features; caps->desc; caps++) + for (caps = cap_array; caps->desc; caps++) if (caps->capability == cap && caps->matches) return caps->matches(caps, SCOPE_LOCAL_CPU); return false; } +extern const struct arm64_cpu_capabilities arm64_errata[]; + +bool this_cpu_has_cap(unsigned int cap) +{ + return (__this_cpu_has_cap(arm64_features, cap) || + __this_cpu_has_cap(arm64_errata, cap)); +} + void __init setup_cpu_features(void) { u32 cwg; diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index 75a0f8acef66..fd691087dc9a 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -30,7 +30,7 @@ int arm_cpuidle_init(unsigned int cpu) } /** - * cpu_suspend() - function to enter a low-power idle state + * arm_cpuidle_suspend() - function to enter a low-power idle state * @arg: argument to pass to CPU suspend operations * * Return: 0 on success, -EOPNOTSUPP if CPU suspend hook not initialized, CPU diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 3a63954a8b14..b884a926a632 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -474,6 +474,7 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, shift = 10; break; case AARCH64_INSN_REGTYPE_RM: + case AARCH64_INSN_REGTYPE_RS: shift = 16; break; default: @@ -757,6 +758,111 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, offset >> shift); } +u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg, + enum aarch64_insn_register base, + enum aarch64_insn_register state, + enum aarch64_insn_size_type size, + enum aarch64_insn_ldst_type type) +{ + u32 insn; + + switch (type) { + case AARCH64_INSN_LDST_LOAD_EX: + insn = aarch64_insn_get_load_ex_value(); + break; + case AARCH64_INSN_LDST_STORE_EX: + insn = aarch64_insn_get_store_ex_value(); + break; + default: + pr_err("%s: unknown load/store exclusive encoding %d\n", __func__, type); + return AARCH64_BREAK_FAULT; + } + + insn = aarch64_insn_encode_ldst_size(size, insn); + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, + reg); + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, + base); + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn, + AARCH64_INSN_REG_ZR); + + return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn, + state); +} + +static u32 aarch64_insn_encode_prfm_imm(enum aarch64_insn_prfm_type type, + enum aarch64_insn_prfm_target target, + enum aarch64_insn_prfm_policy policy, + u32 insn) +{ + u32 imm_type = 0, imm_target = 0, imm_policy = 0; + + switch (type) { + case AARCH64_INSN_PRFM_TYPE_PLD: + break; + case AARCH64_INSN_PRFM_TYPE_PLI: + imm_type = BIT(0); + break; + case AARCH64_INSN_PRFM_TYPE_PST: + imm_type = BIT(1); + break; + default: + pr_err("%s: unknown prfm type encoding %d\n", __func__, type); + return AARCH64_BREAK_FAULT; + } + + switch (target) { + case AARCH64_INSN_PRFM_TARGET_L1: + break; + case AARCH64_INSN_PRFM_TARGET_L2: + imm_target = BIT(0); + break; + case AARCH64_INSN_PRFM_TARGET_L3: + imm_target = BIT(1); + break; + default: + pr_err("%s: unknown prfm target encoding %d\n", __func__, target); + return AARCH64_BREAK_FAULT; + } + + switch (policy) { + case AARCH64_INSN_PRFM_POLICY_KEEP: + break; + case AARCH64_INSN_PRFM_POLICY_STRM: + imm_policy = BIT(0); + break; + default: + pr_err("%s: unknown prfm policy encoding %d\n", __func__, policy); + return AARCH64_BREAK_FAULT; + } + + /* In this case, imm5 is encoded into Rt field. */ + insn &= ~GENMASK(4, 0); + insn |= imm_policy | (imm_target << 1) | (imm_type << 3); + + return insn; +} + +u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base, + enum aarch64_insn_prfm_type type, + enum aarch64_insn_prfm_target target, + enum aarch64_insn_prfm_policy policy) +{ + u32 insn = aarch64_insn_get_prfm_value(); + + insn = aarch64_insn_encode_ldst_size(AARCH64_INSN_SIZE_64, insn); + + insn = aarch64_insn_encode_prfm_imm(type, target, policy, insn); + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, + base); + + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, 0); +} + u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, enum aarch64_insn_register src, int imm, enum aarch64_insn_variant variant, diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index 769f24ef628c..d7e90d97f5c4 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -131,11 +131,15 @@ u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset) /* * The kernel Image should not extend across a 1GB/32MB/512MB alignment * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this - * happens, increase the KASLR offset by the size of the kernel image. + * happens, increase the KASLR offset by the size of the kernel image + * rounded up by SWAPPER_BLOCK_SIZE. */ if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) != - (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT)) - offset = (offset + (u64)(_end - _text)) & mask; + (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT)) { + u64 kimg_sz = _end - _text; + offset = (offset + round_up(kimg_sz, SWAPPER_BLOCK_SIZE)) + & mask; + } if (IS_ENABLED(CONFIG_KASAN)) /* diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index 2a07aae5b8a2..c5c45942fb6e 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -372,12 +372,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr) return 0; } -int __kprobes kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - return NOTIFY_DONE; -} - static void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur_kprobe; diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index ef1caae02110..9b1036570586 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -944,7 +944,7 @@ static bool have_cpu_die(void) #ifdef CONFIG_HOTPLUG_CPU int any_cpu = raw_smp_processor_id(); - if (cpu_ops[any_cpu]->cpu_die) + if (cpu_ops[any_cpu] && cpu_ops[any_cpu]->cpu_die) return true; #endif return false; diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index e52be6aa44ee..1de444e6c669 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -505,6 +505,14 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + pt_regs_write_reg(regs, rt, arch_counter_get_cntvct()); + regs->pc += 4; +} + struct sys64_hook { unsigned int esr_mask; unsigned int esr_val; @@ -523,6 +531,12 @@ static struct sys64_hook sys64_hooks[] = { .esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ, .handler = ctr_read_handler, }, + { + /* Trap read access to CNTVCT_EL0 */ + .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, + .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT, + .handler = cntvct_read_handler, + }, {}, }; diff --git a/arch/arm64/kernel/vdso/.gitignore b/arch/arm64/kernel/vdso/.gitignore index b8cc94e9698b..f8b69d84238e 100644 --- a/arch/arm64/kernel/vdso/.gitignore +++ b/arch/arm64/kernel/vdso/.gitignore @@ -1,2 +1 @@ vdso.lds -vdso-offsets.h diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 1bfe30dfbfe7..fa1b18e364fc 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -135,7 +135,19 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) return ret; } +static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + u32 hsr = kvm_vcpu_get_hsr(vcpu); + + kvm_pr_unimpl("Unknown exception class: hsr: %#08x -- %s\n", + hsr, esr_get_class_string(hsr)); + + kvm_inject_undefined(vcpu); + return 1; +} + static exit_handle_fn arm_exit_handlers[] = { + [0 ... ESR_ELx_EC_MAX] = kvm_handle_unknown_ec, [ESR_ELx_EC_WFx] = kvm_handle_wfx, [ESR_ELx_EC_CP15_32] = kvm_handle_cp15_32, [ESR_ELx_EC_CP15_64] = kvm_handle_cp15_64, @@ -162,13 +174,6 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) u32 hsr = kvm_vcpu_get_hsr(vcpu); u8 hsr_ec = ESR_ELx_EC(hsr); - if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || - !arm_exit_handlers[hsr_ec]) { - kvm_err("Unknown exception class: hsr: %#08x -- %s\n", - hsr, esr_get_class_string(hsr)); - BUG(); - } - return arm_exit_handlers[hsr_ec]; } diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c index e8e7ba2bc11f..9e1d2b75eecd 100644 --- a/arch/arm64/kvm/hyp/tlb.c +++ b/arch/arm64/kvm/hyp/tlb.c @@ -18,14 +18,62 @@ #include <asm/kvm_hyp.h> #include <asm/tlbflush.h> +static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm) +{ + u64 val; + + /* + * With VHE enabled, we have HCR_EL2.{E2H,TGE} = {1,1}, and + * most TLB operations target EL2/EL0. In order to affect the + * guest TLBs (EL1/EL0), we need to change one of these two + * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so + * let's flip TGE before executing the TLB operation. + */ + write_sysreg(kvm->arch.vttbr, vttbr_el2); + val = read_sysreg(hcr_el2); + val &= ~HCR_TGE; + write_sysreg(val, hcr_el2); + isb(); +} + +static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm) +{ + write_sysreg(kvm->arch.vttbr, vttbr_el2); + isb(); +} + +static hyp_alternate_select(__tlb_switch_to_guest, + __tlb_switch_to_guest_nvhe, + __tlb_switch_to_guest_vhe, + ARM64_HAS_VIRT_HOST_EXTN); + +static void __hyp_text __tlb_switch_to_host_vhe(struct kvm *kvm) +{ + /* + * We're done with the TLB operation, let's restore the host's + * view of HCR_EL2. + */ + write_sysreg(0, vttbr_el2); + write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); +} + +static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm) +{ + write_sysreg(0, vttbr_el2); +} + +static hyp_alternate_select(__tlb_switch_to_host, + __tlb_switch_to_host_nvhe, + __tlb_switch_to_host_vhe, + ARM64_HAS_VIRT_HOST_EXTN); + void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) { dsb(ishst); /* Switch to requested VMID */ kvm = kern_hyp_va(kvm); - write_sysreg(kvm->arch.vttbr, vttbr_el2); - isb(); + __tlb_switch_to_guest()(kvm); /* * We could do so much better if we had the VA as well. @@ -46,7 +94,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) dsb(ish); isb(); - write_sysreg(0, vttbr_el2); + __tlb_switch_to_host()(kvm); } void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) @@ -55,14 +103,13 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) /* Switch to requested VMID */ kvm = kern_hyp_va(kvm); - write_sysreg(kvm->arch.vttbr, vttbr_el2); - isb(); + __tlb_switch_to_guest()(kvm); __tlbi(vmalls12e1is); dsb(ish); isb(); - write_sysreg(0, vttbr_el2); + __tlb_switch_to_host()(kvm); } void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) @@ -70,14 +117,13 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm); /* Switch to requested VMID */ - write_sysreg(kvm->arch.vttbr, vttbr_el2); - isb(); + __tlb_switch_to_guest()(kvm); __tlbi(vmalle1); dsb(nsh); isb(); - write_sysreg(0, vttbr_el2); + __tlb_switch_to_host()(kvm); } void __hyp_text __kvm_flush_vm_context(void) diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S index 47184c3a97da..b24a830419ad 100644 --- a/arch/arm64/lib/copy_in_user.S +++ b/arch/arm64/lib/copy_in_user.S @@ -64,14 +64,14 @@ .endm end .req x5 -ENTRY(__copy_in_user) +ENTRY(raw_copy_in_user) uaccess_enable_not_uao x3, x4 add end, x0, x2 #include "copy_template.S" uaccess_disable_not_uao x3 mov x0, #0 ret -ENDPROC(__copy_in_user) +ENDPROC(raw_copy_in_user) .section .fixup,"ax" .align 2 diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 4bf899fb451b..1b35b8bddbfb 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -42,7 +42,20 @@ #include <asm/pgtable.h> #include <asm/tlbflush.h> -static const char *fault_name(unsigned int esr); +struct fault_info { + int (*fn)(unsigned long addr, unsigned int esr, + struct pt_regs *regs); + int sig; + int code; + const char *name; +}; + +static const struct fault_info fault_info[]; + +static inline const struct fault_info *esr_to_fault_info(unsigned int esr) +{ + return fault_info + (esr & 63); +} #ifdef CONFIG_KPROBES static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr) @@ -197,10 +210,12 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, struct pt_regs *regs) { struct siginfo si; + const struct fault_info *inf; if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) { + inf = esr_to_fault_info(esr); pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n", - tsk->comm, task_pid_nr(tsk), fault_name(esr), sig, + tsk->comm, task_pid_nr(tsk), inf->name, sig, addr, esr); show_pte(tsk->mm, addr); show_regs(regs); @@ -219,14 +234,16 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re { struct task_struct *tsk = current; struct mm_struct *mm = tsk->active_mm; + const struct fault_info *inf; /* * If we are in kernel mode at this point, we have no context to * handle this fault with. */ - if (user_mode(regs)) - __do_user_fault(tsk, addr, esr, SIGSEGV, SEGV_MAPERR, regs); - else + if (user_mode(regs)) { + inf = esr_to_fault_info(esr); + __do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs); + } else __do_kernel_fault(mm, addr, esr, regs); } @@ -488,12 +505,7 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) return 1; } -static const struct fault_info { - int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); - int sig; - int code; - const char *name; -} fault_info[] = { +static const struct fault_info fault_info[] = { { do_bad, SIGBUS, 0, "ttbr address size fault" }, { do_bad, SIGBUS, 0, "level 1 address size fault" }, { do_bad, SIGBUS, 0, "level 2 address size fault" }, @@ -560,19 +572,13 @@ static const struct fault_info { { do_bad, SIGBUS, 0, "unknown 63" }, }; -static const char *fault_name(unsigned int esr) -{ - const struct fault_info *inf = fault_info + (esr & 63); - return inf->name; -} - /* * Dispatch a data abort to the relevant handler. */ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - const struct fault_info *inf = fault_info + (esr & 63); + const struct fault_info *inf = esr_to_fault_info(esr); struct siginfo info; if (!inf->fn(addr, esr, regs)) diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index e25584d72396..7514a000e361 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -294,10 +294,6 @@ static __init int setup_hugepagesz(char *opt) hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); } else if (ps == PUD_SIZE) { hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); - } else if (ps == (PAGE_SIZE * CONT_PTES)) { - hugetlb_add_hstate(CONT_PTE_SHIFT); - } else if (ps == (PMD_SIZE * CONT_PMDS)) { - hugetlb_add_hstate((PMD_SHIFT + CONT_PMD_SHIFT) - PAGE_SHIFT); } else { hugetlb_bad_size(); pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10); @@ -306,13 +302,3 @@ static __init int setup_hugepagesz(char *opt) return 1; } __setup("hugepagesz=", setup_hugepagesz); - -#ifdef CONFIG_ARM64_64K_PAGES -static __init int add_default_hugepagesz(void) -{ - if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL) - hugetlb_add_hstate(CONT_PTE_SHIFT); - return 0; -} -arch_initcall(add_default_hugepagesz); -#endif diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index 55d1e9205543..687a358a3733 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -162,7 +162,7 @@ void __init kasan_init(void) clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); vmemmap_populate(kimg_shadow_start, kimg_shadow_end, - pfn_to_nid(virt_to_pfn(_text))); + pfn_to_nid(virt_to_pfn(lm_alias(_text)))); /* * vmemmap_populate() has populated the shadow region that covers the diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h index 7c16e547ccb2..b02a9268dfbf 100644 --- a/arch/arm64/net/bpf_jit.h +++ b/arch/arm64/net/bpf_jit.h @@ -83,6 +83,25 @@ /* Rt = Rn[0]; Rt2 = Rn[8]; Rn += 16; */ #define A64_POP(Rt, Rt2, Rn) A64_LS_PAIR(Rt, Rt2, Rn, 16, LOAD, POST_INDEX) +/* Load/store exclusive */ +#define A64_SIZE(sf) \ + ((sf) ? AARCH64_INSN_SIZE_64 : AARCH64_INSN_SIZE_32) +#define A64_LSX(sf, Rt, Rn, Rs, type) \ + aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \ + AARCH64_INSN_LDST_##type) +/* Rt = [Rn]; (atomic) */ +#define A64_LDXR(sf, Rt, Rn) \ + A64_LSX(sf, Rt, Rn, A64_ZR, LOAD_EX) +/* [Rn] = Rt; (atomic) Rs = [state] */ +#define A64_STXR(sf, Rt, Rn, Rs) \ + A64_LSX(sf, Rt, Rn, Rs, STORE_EX) + +/* Prefetch */ +#define A64_PRFM(Rn, type, target, policy) \ + aarch64_insn_gen_prefetch(Rn, AARCH64_INSN_PRFM_TYPE_##type, \ + AARCH64_INSN_PRFM_TARGET_##target, \ + AARCH64_INSN_PRFM_POLICY_##policy) + /* Add/subtract (immediate) */ #define A64_ADDSUB_IMM(sf, Rd, Rn, imm12, type) \ aarch64_insn_gen_add_sub_imm(Rd, Rn, imm12, \ diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index a785554916c0..d68abde52740 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -321,6 +321,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) const s32 imm = insn->imm; const int i = insn - ctx->prog->insnsi; const bool is64 = BPF_CLASS(code) == BPF_ALU64; + const bool isdw = BPF_SIZE(code) == BPF_DW; u8 jmp_cond; s32 jmp_offset; @@ -604,15 +605,6 @@ emit_cond_jmp: const struct bpf_insn insn1 = insn[1]; u64 imm64; - if (insn1.code != 0 || insn1.src_reg != 0 || - insn1.dst_reg != 0 || insn1.off != 0) { - /* Note: verifier in BPF core must catch invalid - * instructions. - */ - pr_err_once("Invalid BPF_LD_IMM64 instruction\n"); - return -EINVAL; - } - imm64 = (u64)insn1.imm << 32 | (u32)imm; emit_a64_mov_i64(dst, imm64, ctx); @@ -690,7 +682,16 @@ emit_cond_jmp: case BPF_STX | BPF_XADD | BPF_W: /* STX XADD: lock *(u64 *)(dst + off) += src */ case BPF_STX | BPF_XADD | BPF_DW: - goto notyet; + emit_a64_mov_i(1, tmp, off, ctx); + emit(A64_ADD(1, tmp, tmp, dst), ctx); + emit(A64_PRFM(tmp, PST, L1, STRM), ctx); + emit(A64_LDXR(isdw, tmp2, tmp), ctx); + emit(A64_ADD(isdw, tmp2, tmp2, src), ctx); + emit(A64_STXR(isdw, tmp2, tmp, tmp2), ctx); + jmp_offset = -3; + check_imm19(jmp_offset); + emit(A64_CBNZ(0, tmp2, jmp_offset), ctx); + break; /* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */ case BPF_LD | BPF_ABS | BPF_W: @@ -757,10 +758,6 @@ emit_cond_jmp: } break; } -notyet: - pr_info_once("*** NOT YET: opcode %02x ***\n", code); - return -EFAULT; - default: pr_err_once("unknown opcode %02x\n", code); return -EINVAL; @@ -779,14 +776,14 @@ static int build_body(struct jit_ctx *ctx) int ret; ret = build_insn(insn, ctx); - - if (ctx->image == NULL) - ctx->offset[i] = ctx->idx; - if (ret > 0) { i++; + if (ctx->image == NULL) + ctx->offset[i] = ctx->idx; continue; } + if (ctx->image == NULL) + ctx->offset[i] = ctx->idx; if (ret) return ret; } diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig deleted file mode 100644 index 7e75d45e20cd..000000000000 --- a/arch/avr32/Kconfig +++ /dev/null @@ -1,288 +0,0 @@ -config AVR32 - def_bool y - # With EXPERT=n, we get lots of stuff automatically selected - # that we usually don't need on AVR32. - select EXPERT - select HAVE_CLK - select HAVE_EXIT_THREAD - select HAVE_OPROFILE - select HAVE_KPROBES - select VIRT_TO_BUS - select GENERIC_IRQ_PROBE - select GENERIC_ATOMIC64 - select HARDIRQS_SW_RESEND - select GENERIC_IRQ_SHOW - select ARCH_HAVE_CUSTOM_GPIO_H - select ARCH_WANT_IPC_PARSE_VERSION - select ARCH_HAVE_NMI_SAFE_CMPXCHG - select GENERIC_CLOCKEVENTS - select HAVE_MOD_ARCH_SPECIFIC - select MODULES_USE_ELF_RELA - select HAVE_NMI - help - AVR32 is a high-performance 32-bit RISC microprocessor core, - designed for cost-sensitive embedded applications, with particular - emphasis on low power consumption and high code density. - - There is an AVR32 Linux project with a web page at - http://avr32linux.org/. - -config STACKTRACE_SUPPORT - def_bool y - -config LOCKDEP_SUPPORT - def_bool y - -config TRACE_IRQFLAGS_SUPPORT - def_bool y - -config RWSEM_GENERIC_SPINLOCK - def_bool y - -config RWSEM_XCHGADD_ALGORITHM - def_bool n - -config ARCH_HAS_ILOG2_U32 - def_bool n - -config ARCH_HAS_ILOG2_U64 - def_bool n - -config GENERIC_HWEIGHT - def_bool y - -config GENERIC_CALIBRATE_DELAY - def_bool y - -config GENERIC_BUG - def_bool y - depends on BUG - -source "init/Kconfig" - -source "kernel/Kconfig.freezer" - -menu "System Type and features" - -config SUBARCH_AVR32B - bool -config MMU - bool -config PERFORMANCE_COUNTERS - bool - -config PLATFORM_AT32AP - bool - select SUBARCH_AVR32B - select MMU - select PERFORMANCE_COUNTERS - select GPIOLIB - select GENERIC_ALLOCATOR - select HAVE_FB_ATMEL - -# -# CPU types -# - -# AP7000 derivatives -config CPU_AT32AP700X - bool - select PLATFORM_AT32AP -config CPU_AT32AP7000 - bool - select CPU_AT32AP700X -config CPU_AT32AP7001 - bool - select CPU_AT32AP700X -config CPU_AT32AP7002 - bool - select CPU_AT32AP700X - -# AP700X boards -config BOARD_ATNGW100_COMMON - bool - select CPU_AT32AP7000 - -choice - prompt "AVR32 board type" - default BOARD_ATSTK1000 - -config BOARD_ATSTK1000 - bool "ATSTK1000 evaluation board" - -config BOARD_ATNGW100_MKI - bool "ATNGW100 Network Gateway" - select BOARD_ATNGW100_COMMON - -config BOARD_ATNGW100_MKII - bool "ATNGW100 mkII Network Gateway" - select BOARD_ATNGW100_COMMON - -config BOARD_HAMMERHEAD - bool "Hammerhead board" - select CPU_AT32AP7000 - select USB_ARCH_HAS_HCD - help - The Hammerhead platform is built around an AVR32 32-bit microcontroller from Atmel. - It offers versatile peripherals, such as ethernet, usb device, usb host etc. - - The board also incorporates a power supply and is a Power over Ethernet (PoE) Powered - Device (PD). - - Additionally, a Cyclone III FPGA from Altera is integrated on the board. The FPGA is - mapped into the 32-bit AVR memory bus. The FPGA offers two DDR2 SDRAM interfaces, which - will cover even the most exceptional need of memory bandwidth. Together with the onboard - video decoder the board is ready for video processing. - - For more information see: http://www.miromico.ch/index.php/hammerhead.html - -config BOARD_FAVR_32 - bool "Favr-32 LCD-board" - select CPU_AT32AP7000 - -config BOARD_MERISC - bool "Merisc board" - select CPU_AT32AP7000 - help - Merisc is the family name for a range of AVR32-based boards. - - The boards are designed to be used in a man-machine - interfacing environment, utilizing a touch-based graphical - user interface. They host a vast range of I/O peripherals as - well as a large SDRAM & Flash memory bank. - - For more information see: http://www.martinsson.se/merisc - -config BOARD_MIMC200 - bool "MIMC200 CPU board" - select CPU_AT32AP7000 -endchoice - -source "arch/avr32/boards/atstk1000/Kconfig" -source "arch/avr32/boards/atngw100/Kconfig" -source "arch/avr32/boards/hammerhead/Kconfig" -source "arch/avr32/boards/favr-32/Kconfig" -source "arch/avr32/boards/merisc/Kconfig" - -choice - prompt "Boot loader type" - default LOADER_U_BOOT - -config LOADER_U_BOOT - bool "U-Boot (or similar) bootloader" -endchoice - -source "arch/avr32/mach-at32ap/Kconfig" - -config LOAD_ADDRESS - hex - default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP700X=y - -config ENTRY_ADDRESS - hex - default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP700X=y - -config PHYS_OFFSET - hex - default 0x10000000 if CPU_AT32AP700X=y - -source "kernel/Kconfig.preempt" - -config QUICKLIST - def_bool y - -config ARCH_HAVE_MEMORY_PRESENT - def_bool n - -config NEED_NODE_MEMMAP_SIZE - def_bool n - -config ARCH_FLATMEM_ENABLE - def_bool y - -config ARCH_DISCONTIGMEM_ENABLE - def_bool n - -config ARCH_SPARSEMEM_ENABLE - def_bool n - -config NODES_SHIFT - int - default "2" - depends on NEED_MULTIPLE_NODES - -source "mm/Kconfig" - -config OWNERSHIP_TRACE - bool "Ownership trace support" - default y - help - Say Y to generate an Ownership Trace message on every context switch, - enabling Nexus-compliant debuggers to keep track of the PID of the - currently executing task. - -config NMI_DEBUGGING - bool "NMI Debugging" - default n - help - Say Y here and pass the nmi_debug command-line parameter to - the kernel to turn on NMI debugging. Depending on the value - of the nmi_debug option, various pieces of information will - be dumped to the console when a Non-Maskable Interrupt - happens. - -# FPU emulation goes here - -source "kernel/Kconfig.hz" - -config CMDLINE - string "Default kernel command line" - default "" - help - If you don't have a boot loader capable of passing a command line string - to the kernel, you may specify one here. As a minimum, you should specify - the memory size and the root device (e.g., mem=8M, root=/dev/nfs). - -endmenu - -menu "Power management options" - -source "kernel/power/Kconfig" - -config ARCH_SUSPEND_POSSIBLE - def_bool y - -menu "CPU Frequency scaling" -source "drivers/cpufreq/Kconfig" -endmenu - -endmenu - -menu "Bus options" - -config PCI - bool - -source "drivers/pci/Kconfig" - -source "drivers/pcmcia/Kconfig" - -endmenu - -menu "Executable file formats" -source "fs/Kconfig.binfmt" -endmenu - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "fs/Kconfig" - -source "arch/avr32/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/arch/avr32/Kconfig.debug b/arch/avr32/Kconfig.debug deleted file mode 100644 index 2283933a9a93..000000000000 --- a/arch/avr32/Kconfig.debug +++ /dev/null @@ -1,9 +0,0 @@ -menu "Kernel hacking" - -config TRACE_IRQFLAGS_SUPPORT - bool - default y - -source "lib/Kconfig.debug" - -endmenu diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile deleted file mode 100644 index dba48a5d5bb9..000000000000 --- a/arch/avr32/Makefile +++ /dev/null @@ -1,84 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2004-2006 Atmel Corporation. - -# Default target when executing plain make -.PHONY: all -all: uImage vmlinux.elf - -KBUILD_DEFCONFIG := atstk1002_defconfig - -KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic -D__linux__ -KBUILD_AFLAGS += -mrelax -mno-pic -KBUILD_CFLAGS_MODULE += -mno-relax -LDFLAGS_vmlinux += --relax - -cpuflags-$(CONFIG_PLATFORM_AT32AP) += -march=ap - -KBUILD_CFLAGS += $(cpuflags-y) -KBUILD_AFLAGS += $(cpuflags-y) - -CHECKFLAGS += -D__avr32__ -D__BIG_ENDIAN - -machine-$(CONFIG_PLATFORM_AT32AP) := at32ap -machdirs := $(patsubst %,arch/avr32/mach-%/, $(machine-y)) - -KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs)) - -head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o -head-y += arch/avr32/kernel/head.o -core-y += $(machdirs) -core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/ -core-$(CONFIG_BOARD_ATNGW100_COMMON) += arch/avr32/boards/atngw100/ -core-$(CONFIG_BOARD_HAMMERHEAD) += arch/avr32/boards/hammerhead/ -core-$(CONFIG_BOARD_FAVR_32) += arch/avr32/boards/favr-32/ -core-$(CONFIG_BOARD_MERISC) += arch/avr32/boards/merisc/ -core-$(CONFIG_BOARD_MIMC200) += arch/avr32/boards/mimc200/ -core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/ -core-y += arch/avr32/kernel/ -core-y += arch/avr32/mm/ -drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/ -libs-y += arch/avr32/lib/ - -BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec - -.PHONY: $(BOOT_TARGETS) install - -boot := arch/$(ARCH)/boot/images - - KBUILD_IMAGE := $(boot)/uImage -vmlinux.elf: KBUILD_IMAGE := $(boot)/vmlinux.elf -vmlinux.cso: KBUILD_IMAGE := $(boot)/vmlinux.cso -uImage.srec: KBUILD_IMAGE := $(boot)/uImage.srec -uImage: KBUILD_IMAGE := $(boot)/uImage - -quiet_cmd_listing = LST $@ - cmd_listing = avr32-linux-objdump $(OBJDUMPFLAGS) -lS $< > $@ -quiet_cmd_disasm = DIS $@ - cmd_disasm = avr32-linux-objdump $(OBJDUMPFLAGS) -d $< > $@ - -vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - -install: vmlinux - $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ - -vmlinux.s: vmlinux - $(call if_changed,disasm) - -vmlinux.lst: vmlinux - $(call if_changed,listing) - -CLEAN_FILES += vmlinux.s vmlinux.lst - -archclean: - $(Q)$(MAKE) $(clean)=$(boot) - -define archhelp - @echo '* vmlinux.elf - ELF image with load address 0' - @echo ' vmlinux.cso - PathFinder CSO image' - @echo '* uImage - Create a bootable image for U-Boot' -endef diff --git a/arch/avr32/boards/atngw100/Kconfig b/arch/avr32/boards/atngw100/Kconfig deleted file mode 100644 index 4e55617ade2d..000000000000 --- a/arch/avr32/boards/atngw100/Kconfig +++ /dev/null @@ -1,65 +0,0 @@ -# NGW100 customization - -if BOARD_ATNGW100_COMMON - -config BOARD_ATNGW100_MKII_LCD - bool "Enable ATNGW100 mkII LCD interface" - depends on BOARD_ATNGW100_MKII - help - This enables the LCD controller (LCDC) in the AT32AP7000. Since the - LCDC is multiplexed with MACB1 (LAN) Ethernet port, only one can be - enabled at a time. - - This choice enables the LCDC and disables the MACB1 interface marked - LAN on the PCB. - -choice - prompt "Select an NGW100 add-on board to support" - default BOARD_ATNGW100_ADDON_NONE - -config BOARD_ATNGW100_ADDON_NONE - bool "None" - -config BOARD_ATNGW100_EVKLCD10X - bool "EVKLCD10X addon board" - depends on BOARD_ATNGW100_MKI || BOARD_ATNGW100_MKII_LCD - help - This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA) - addon board for the NGW100 and NGW100 mkII. By enabling this the LCD - controller and AC97 controller is added as platform devices. - -config BOARD_ATNGW100_MRMT - bool "Mediama RMT1/2 add-on board" - help - This enables support for the Mediama RMT1 or RMT2 board. - RMT provides LCD support, AC97 codec and other - optional peripherals to the Atmel NGW100. - - This choice disables the detect pin and the write-protect pin for the - MCI platform device, since it conflicts with the LCD platform device. - The MCI pins can be reenabled by editing the "add device function" but - this may break the setup for other displays that use these pins. - -endchoice - -choice - prompt "LCD panel resolution on EVKLCD10X" - depends on BOARD_ATNGW100_EVKLCD10X - default BOARD_ATNGW100_EVKLCD10X_VGA - -config BOARD_ATNGW100_EVKLCD10X_QVGA - bool "QVGA (320x240)" - -config BOARD_ATNGW100_EVKLCD10X_VGA - bool "VGA (640x480)" - -config BOARD_ATNGW100_EVKLCD10X_POW_QVGA - bool "Powertip QVGA (320x240)" - -endchoice - -if BOARD_ATNGW100_MRMT -source "arch/avr32/boards/atngw100/Kconfig_mrmt" -endif - -endif # BOARD_ATNGW100_COMMON diff --git a/arch/avr32/boards/atngw100/Kconfig_mrmt b/arch/avr32/boards/atngw100/Kconfig_mrmt deleted file mode 100644 index 9a199a207f3c..000000000000 --- a/arch/avr32/boards/atngw100/Kconfig_mrmt +++ /dev/null @@ -1,80 +0,0 @@ -# RMT for NGW100 customization - -choice - prompt "RMT Version" - help - Select the RMTx board version. - -config BOARD_MRMT_REV1 - bool "RMT1" -config BOARD_MRMT_REV2 - bool "RMT2" - -endchoice - -config BOARD_MRMT_AC97 - bool "Enable AC97 CODEC" - help - Enable the UCB1400 AC97 CODEC driver. - -choice - prompt "Touchscreen Driver" - default BOARD_MRMT_ADS7846_TS - -config BOARD_MRMT_UCB1400_TS - bool "Use UCB1400 Touchscreen" - -config BOARD_MRMT_ADS7846_TS - bool "Use ADS7846 Touchscreen" - -endchoice - -choice - prompt "RMTx LCD Selection" - default BOARD_MRMT_LCD_DISABLE - -config BOARD_MRMT_LCD_DISABLE - bool "LCD Disabled" - -config BOARD_MRMT_LCD_LQ043T3DX0X - bool "Sharp LQ043T3DX0x or compatible" - help - If using RMT2, be sure to load the resistor pack selectors accordingly - -if BOARD_MRMT_REV2 -config BOARD_MRMT_LCD_KWH043GM08 - bool "Formike KWH043GM08 or compatible" - help - Be sure to load the RMT2 resistor pack selectors accordingly -endif - -endchoice - -if !BOARD_MRMT_LCD_DISABLE -config BOARD_MRMT_BL_PWM - bool "Use PWM control for LCD Backlight" - help - Use PWM driver for controlling LCD Backlight. - Otherwise, LCD Backlight is always on. -endif - -config BOARD_MRMT_RTC_I2C - bool "Use External RTC on I2C Bus" - help - RMT1 has an optional RTC device on the I2C bus. - It is a SII S35390A. Be sure to select the - matching RTC driver. - -choice - prompt "Wireless Module on ttyS2" - default BOARD_MRMT_WIRELESS_ZB - -config BOARD_MRMT_WIRELESS_ZB - bool "Use ZigBee/802.15.4 Module" - -config BOARD_MRMT_WIRELESS_BT - bool "Use Bluetooth (HCI) Module" - -config BOARD_MRMT_WIRELESS_NONE - bool "Not Installed" -endchoice diff --git a/arch/avr32/boards/atngw100/Makefile b/arch/avr32/boards/atngw100/Makefile deleted file mode 100644 index f4ebe42a8254..000000000000 --- a/arch/avr32/boards/atngw100/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += setup.o flash.o -obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X) += evklcd10x.o -obj-$(CONFIG_BOARD_ATNGW100_MRMT) += mrmt.o diff --git a/arch/avr32/boards/atngw100/evklcd10x.c b/arch/avr32/boards/atngw100/evklcd10x.c deleted file mode 100644 index 64919b0da7aa..000000000000 --- a/arch/avr32/boards/atngw100/evklcd10x.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Board-specific setup code for the ATEVKLCD10X addon board to the ATNGW100 - * Network Gateway - * - * Copyright (C) 2008 Atmel Corporation - * - * 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/init.h> -#include <linux/linkage.h> -#include <linux/gpio.h> -#include <linux/fb.h> -#include <linux/platform_device.h> - -#include <video/atmel_lcdc.h> - -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/portmux.h> -#include <mach/board.h> - -#include <sound/atmel-ac97c.h> - -static struct ac97c_platform_data __initdata ac97c0_data = { - .reset_pin = GPIO_PIN_PB(19), -}; - -#ifdef CONFIG_BOARD_ATNGW100_EVKLCD10X_VGA -static struct fb_videomode __initdata tcg057vglad_modes[] = { - { - .name = "640x480 @ 50", - .refresh = 50, - .xres = 640, .yres = 480, - .pixclock = KHZ2PICOS(25180), - - .left_margin = 64, .right_margin = 96, - .upper_margin = 34, .lower_margin = 11, - .hsync_len = 64, .vsync_len = 15, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { - .manufacturer = "KYO", - .monitor = "TCG057VGLAD", - .modedb = tcg057vglad_modes, - .modedb_len = ARRAY_SIZE(tcg057vglad_modes), - .hfmin = 19948, - .hfmax = 31478, - .vfmin = 50, - .vfmax = 67, - .dclkmax = 28330000, -}; - -static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = { - .default_bpp = 16, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &atevklcd10x_default_monspecs, - .guard_time = 2, -}; -#elif CONFIG_BOARD_ATNGW100_EVKLCD10X_QVGA -static struct fb_videomode __initdata tcg057qvlad_modes[] = { - { - .name = "320x240 @ 50", - .refresh = 50, - .xres = 320, .yres = 240, - .pixclock = KHZ2PICOS(6300), - - .left_margin = 34, .right_margin = 46, - .upper_margin = 7, .lower_margin = 15, - .hsync_len = 64, .vsync_len = 12, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { - .manufacturer = "KYO", - .monitor = "TCG057QVLAD", - .modedb = tcg057qvlad_modes, - .modedb_len = ARRAY_SIZE(tcg057qvlad_modes), - .hfmin = 19948, - .hfmax = 31478, - .vfmin = 50, - .vfmax = 67, - .dclkmax = 7000000, -}; - -static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = { - .default_bpp = 16, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &atevklcd10x_default_monspecs, - .guard_time = 2, -}; -#elif CONFIG_BOARD_ATNGW100_EVKLCD10X_POW_QVGA -static struct fb_videomode __initdata ph320240t_modes[] = { - { - .name = "320x240 @ 60", - .refresh = 60, - .xres = 320, .yres = 240, - .pixclock = KHZ2PICOS(6300), - - .left_margin = 38, .right_margin = 20, - .upper_margin = 15, .lower_margin = 5, - .hsync_len = 30, .vsync_len = 3, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { - .manufacturer = "POW", - .monitor = "PH320240T", - .modedb = ph320240t_modes, - .modedb_len = ARRAY_SIZE(ph320240t_modes), - .hfmin = 14400, - .hfmax = 21600, - .vfmin = 50, - .vfmax = 90, - .dclkmax = 6400000, -}; - -static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = { - .default_bpp = 16, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &atevklcd10x_default_monspecs, - .guard_time = 2, -}; -#endif - -static void atevklcd10x_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on) -{ - gpio_set_value(GPIO_PIN_PB(15), on); -} - -static int __init atevklcd10x_init(void) -{ - /* PB15 is connected to the enable line on the boost regulator - * controlling the backlight for the LCD panel. - */ - at32_select_gpio(GPIO_PIN_PB(15), AT32_GPIOF_OUTPUT); - gpio_request(GPIO_PIN_PB(15), "backlight"); - gpio_direction_output(GPIO_PIN_PB(15), 0); - - atevklcd10x_lcdc_data.atmel_lcdfb_power_control = - atevklcd10x_lcdc_power_control; - - at32_add_device_lcdc(0, &atevklcd10x_lcdc_data, - fbmem_start, fbmem_size, -#ifdef CONFIG_BOARD_ATNGW100_MKII - ATMEL_LCDC_PRI_18BIT | ATMEL_LCDC_PC_DVAL -#else - ATMEL_LCDC_ALT_18BIT | ATMEL_LCDC_PE_DVAL -#endif - ); - - at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH); - - return 0; -} -postcore_initcall(atevklcd10x_init); diff --git a/arch/avr32/boards/atngw100/flash.c b/arch/avr32/boards/atngw100/flash.c deleted file mode 100644 index 55ccc9ce4892..000000000000 --- a/arch/avr32/boards/atngw100/flash.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ATNGW100 board-specific flash initialization - * - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> - -#include <mach/smc.h> - -static struct smc_timing flash_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 40, - .ncs_write_setup = 0, - .nwe_setup = 10, - - .ncs_read_pulse = 80, - .nrd_pulse = 40, - .ncs_write_pulse = 65, - .nwe_pulse = 55, - - .read_cycle = 120, - .write_cycle = 120, -}; - -static struct smc_config flash_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 1, -}; - -static struct mtd_partition flash_parts[] = { - { - .name = "u-boot", - .offset = 0x00000000, - .size = 0x00020000, /* 128 KiB */ - .mask_flags = MTD_WRITEABLE, - }, - { - .name = "root", - .offset = 0x00020000, - .size = 0x007d0000, - }, - { - .name = "env", - .offset = 0x007f0000, - .size = 0x00010000, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data flash_data = { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_parts), - .parts = flash_parts, -}; - -static struct resource flash_resource = { - .start = 0x00000000, - .end = 0x007fffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device flash_device = { - .name = "physmap-flash", - .id = 0, - .resource = &flash_resource, - .num_resources = 1, - .dev = { - .platform_data = &flash_data, - }, -}; - -/* This needs to be called after the SMC has been initialized */ -static int __init atngw100_flash_init(void) -{ - int ret; - - smc_set_timing(&flash_config, &flash_timing); - ret = smc_set_configuration(0, &flash_config); - if (ret < 0) { - printk(KERN_ERR "atngw100: failed to set NOR flash timing\n"); - return ret; - } - - platform_device_register(&flash_device); - - return 0; -} -device_initcall(atngw100_flash_init); diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c deleted file mode 100644 index 99b0a7984950..000000000000 --- a/arch/avr32/boards/atngw100/mrmt.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Board-specific setup code for Remote Media Terminal 1 (RMT1) - * add-on board for the ATNGW100 Network Gateway - * - * Copyright (C) 2008 Mediama Technologies - * Based on ATNGW100 Network Gateway (Copyright (C) Atmel) - * - * 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/gpio.h> -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/linkage.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/fb.h> -#include <linux/leds.h> -#include <linux/pwm.h> -#include <linux/leds_pwm.h> -#include <linux/input.h> -#include <linux/gpio_keys.h> -#include <linux/spi/spi.h> -#include <linux/spi/ads7846.h> - -#include <video/atmel_lcdc.h> -#include <sound/atmel-ac97c.h> - -#include <asm/delay.h> -#include <asm/io.h> -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -/* Define board-specifoic GPIO assignments */ -#define PIN_LCD_BL GPIO_PIN_PA(28) -#define PWM_CH_BL 0 /* Must match with GPIO pin definition */ -#define PIN_LCD_DISP GPIO_PIN_PA(31) -#define PIN_AC97_RST_N GPIO_PIN_PA(30) -#define PB_EXTINT_BASE 25 -#define TS_IRQ 0 -#define PIN_TS_EXTINT GPIO_PIN_PB(PB_EXTINT_BASE+TS_IRQ) -#define PIN_PB_LEFT GPIO_PIN_PB(11) -#define PIN_PB_RIGHT GPIO_PIN_PB(12) -#define PIN_PWR_SW_N GPIO_PIN_PB(14) -#define PIN_PWR_ON GPIO_PIN_PB(13) -#define PIN_ZB_RST_N GPIO_PIN_PA(21) -#define PIN_BT_RST GPIO_PIN_PA(22) -#define PIN_LED_SYS GPIO_PIN_PA(16) -#define PIN_LED_A GPIO_PIN_PA(19) -#define PIN_LED_B GPIO_PIN_PE(19) - -#ifdef CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X -/* Sharp LQ043T3DX0x (or compatible) panel */ -static struct fb_videomode __initdata lcd_fb_modes[] = { - { - .name = "480x272 @ 59.94Hz", - .refresh = 59.94, - .xres = 480, .yres = 272, - .pixclock = KHZ2PICOS(9000), - - .left_margin = 2, .right_margin = 2, - .upper_margin = 3, .lower_margin = 9, - .hsync_len = 41, .vsync_len = 1, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata lcd_fb_default_monspecs = { - .manufacturer = "SHA", - .monitor = "LQ043T3DX02", - .modedb = lcd_fb_modes, - .modedb_len = ARRAY_SIZE(lcd_fb_modes), - .hfmin = 14915, - .hfmax = 17638, - .vfmin = 53, - .vfmax = 61, - .dclkmax = 9260000, -}; - -static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = { - .default_bpp = 24, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_INVCLK_NORMAL - | ATMEL_LCDC_MEMOR_BIG), - .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, - .default_monspecs = &lcd_fb_default_monspecs, - .guard_time = 2, -}; -#endif - -#ifdef CONFIG_BOARD_MRMT_LCD_KWH043GM08 -/* Sharp KWH043GM08-Fxx (or compatible) panel */ -static struct fb_videomode __initdata lcd_fb_modes[] = { - { - .name = "480x272 @ 59.94Hz", - .refresh = 59.94, - .xres = 480, .yres = 272, - .pixclock = KHZ2PICOS(9000), - - .left_margin = 2, .right_margin = 2, - .upper_margin = 3, .lower_margin = 9, - .hsync_len = 41, .vsync_len = 1, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata lcd_fb_default_monspecs = { - .manufacturer = "FOR", - .monitor = "KWH043GM08", - .modedb = lcd_fb_modes, - .modedb_len = ARRAY_SIZE(lcd_fb_modes), - .hfmin = 14915, - .hfmax = 17638, - .vfmin = 53, - .vfmax = 61, - .dclkmax = 9260000, -}; - -static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = { - .default_bpp = 24, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_INVCLK_INVERTED - | ATMEL_LCDC_MEMOR_BIG), - .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, - .default_monspecs = &lcd_fb_default_monspecs, - .guard_time = 2, -}; -#endif - -#ifdef CONFIG_BOARD_MRMT_AC97 -static struct ac97c_platform_data __initdata ac97c0_data = { - .reset_pin = PIN_AC97_RST_N, -}; -#endif - -#ifdef CONFIG_BOARD_MRMT_UCB1400_TS -/* NOTE: IRQ assignment relies on kernel module parameter */ -static struct platform_device rmt_ts_device = { - .name = "ucb1400_ts", - .id = -1, -}; -#endif - -#ifdef CONFIG_BOARD_MRMT_BL_PWM -/* PWM LEDs: LCD Backlight, etc */ -static struct pwm_lookup pwm_lookup[] = { - PWM_LOOKUP("at91sam9rl-pwm", PWM_CH_BL, "leds_pwm", "ds1", - 5000, PWM_POLARITY_INVERSED), -}; - -static struct led_pwm pwm_leds[] = { - { - .name = "backlight", - .max_brightness = 255, - }, -}; - -static struct led_pwm_platform_data pwm_data = { - .num_leds = ARRAY_SIZE(pwm_leds), - .leds = pwm_leds, -}; - -static struct platform_device leds_pwm = { - .name = "leds_pwm", - .id = -1, - .dev = { - .platform_data = &pwm_data, - }, -}; -#endif - -#ifdef CONFIG_BOARD_MRMT_ADS7846_TS -static int ads7846_pendown_state(void) -{ - return !gpio_get_value( PIN_TS_EXTINT ); /* PENIRQ.*/ -} - -static struct ads7846_platform_data ads_info = { - .model = 7846, - .keep_vref_on = 0, /* Use external VREF pin */ - .vref_delay_usecs = 0, - .vref_mv = 3300, /* VREF = 3.3V */ - .settle_delay_usecs = 800, - .penirq_recheck_delay_usecs = 800, - .x_plate_ohms = 750, - .y_plate_ohms = 300, - .pressure_max = 4096, - .debounce_max = 1, - .debounce_rep = 0, - .debounce_tol = (~0), - .get_pendown_state = ads7846_pendown_state, - .filter = NULL, - .filter_init = NULL, -}; - -static struct spi_board_info spi01_board_info[] __initdata = { - { - .modalias = "ads7846", - .max_speed_hz = 31250*26, - .bus_num = 0, - .chip_select = 1, - .platform_data = &ads_info, - .irq = AT32_EXTINT(TS_IRQ), - }, -}; -#endif - -/* GPIO Keys: left, right, power, etc */ -static const struct gpio_keys_button rmt_gpio_keys_buttons[] = { - [0] = { - .type = EV_KEY, - .code = KEY_POWER, - .gpio = PIN_PWR_SW_N, - .active_low = 1, - .desc = "power button", - }, - [1] = { - .type = EV_KEY, - .code = KEY_LEFT, - .gpio = PIN_PB_LEFT, - .active_low = 1, - .desc = "left button", - }, - [2] = { - .type = EV_KEY, - .code = KEY_RIGHT, - .gpio = PIN_PB_RIGHT, - .active_low = 1, - .desc = "right button", - }, -}; - -static const struct gpio_keys_platform_data rmt_gpio_keys_data = { - .nbuttons = ARRAY_SIZE(rmt_gpio_keys_buttons), - .buttons = (void *) rmt_gpio_keys_buttons, -}; - -static struct platform_device rmt_gpio_keys = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = (void *) &rmt_gpio_keys_data, - } -}; - -#ifdef CONFIG_BOARD_MRMT_RTC_I2C -static struct i2c_board_info __initdata mrmt1_i2c_rtc = { - I2C_BOARD_INFO("s35390a", 0x30), - .irq = 0, -}; -#endif - -static void mrmt_power_off(void) -{ - /* PWR_ON=0 will force power off */ - gpio_set_value( PIN_PWR_ON, 0 ); -} - -static int __init mrmt1_init(void) -{ - gpio_set_value( PIN_PWR_ON, 1 ); /* Ensure PWR_ON is enabled */ - - pm_power_off = mrmt_power_off; - - /* Setup USARTS (other than console) */ - at32_map_usart(2, 1, 0); /* USART 2: /dev/ttyS1, RMT1:DB9M */ - at32_map_usart(3, 2, ATMEL_USART_RTS | ATMEL_USART_CTS); - /* USART 3: /dev/ttyS2, RMT1:Wireless, w/ RTS/CTS */ - at32_add_device_usart(1); - at32_add_device_usart(2); - - /* Select GPIO Key pins */ - at32_select_gpio( PIN_PWR_SW_N, AT32_GPIOF_DEGLITCH); - at32_select_gpio( PIN_PB_LEFT, AT32_GPIOF_DEGLITCH); - at32_select_gpio( PIN_PB_RIGHT, AT32_GPIOF_DEGLITCH); - platform_device_register(&rmt_gpio_keys); - -#ifdef CONFIG_BOARD_MRMT_RTC_I2C - i2c_register_board_info(0, &mrmt1_i2c_rtc, 1); -#endif - -#ifndef CONFIG_BOARD_MRMT_LCD_DISABLE - /* User "alternate" LCDC inferface on Port E & D */ - /* NB: exclude LCDC_CC pin, as NGW100 reserves it for other use */ - at32_add_device_lcdc(0, &rmt_lcdc_data, - fbmem_start, fbmem_size, - (ATMEL_LCDC_ALT_24BIT | ATMEL_LCDC_PE_DVAL ) ); -#endif - -#ifdef CONFIG_BOARD_MRMT_AC97 - at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH); -#endif - -#ifdef CONFIG_BOARD_MRMT_ADS7846_TS - /* Select the Touchscreen interrupt pin mode */ - at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ), - GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); - irq_set_irq_type(AT32_EXTINT(TS_IRQ), IRQ_TYPE_EDGE_FALLING); - at32_spi_setup_slaves(0,spi01_board_info,ARRAY_SIZE(spi01_board_info)); - spi_register_board_info(spi01_board_info,ARRAY_SIZE(spi01_board_info)); -#endif - -#ifdef CONFIG_BOARD_MRMT_UCB1400_TS - /* Select the Touchscreen interrupt pin mode */ - at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ), - GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); - platform_device_register(&rmt_ts_device); -#endif - - at32_select_gpio( PIN_LCD_DISP, AT32_GPIOF_OUTPUT ); - gpio_request( PIN_LCD_DISP, "LCD_DISP" ); - gpio_direction_output( PIN_LCD_DISP, 0 ); /* LCD DISP */ -#ifdef CONFIG_BOARD_MRMT_LCD_DISABLE - /* Keep Backlight and DISP off */ - at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT ); - gpio_request( PIN_LCD_BL, "LCD_BL" ); - gpio_direction_output( PIN_LCD_BL, 0 ); /* Backlight */ -#else - gpio_set_value( PIN_LCD_DISP, 1 ); /* DISP asserted first */ -#ifdef CONFIG_BOARD_MRMT_BL_PWM - /* Use PWM for Backlight controls */ - at32_add_device_pwm(1 << PWM_CH_BL); - pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup)); - platform_device_register(&leds_pwm); -#else - /* Backlight always on */ - udelay( 1 ); - at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT ); - gpio_request( PIN_LCD_BL, "LCD_BL" ); - gpio_direction_output( PIN_LCD_BL, 1 ); -#endif -#endif - - /* Make sure BT and Zigbee modules in reset */ - at32_select_gpio( PIN_BT_RST, AT32_GPIOF_OUTPUT ); - gpio_request( PIN_BT_RST, "BT_RST" ); - gpio_direction_output( PIN_BT_RST, 1 ); - /* BT Module in Reset */ - - at32_select_gpio( PIN_ZB_RST_N, AT32_GPIOF_OUTPUT ); - gpio_request( PIN_ZB_RST_N, "ZB_RST_N" ); - gpio_direction_output( PIN_ZB_RST_N, 0 ); - /* XBee Module in Reset */ - -#ifdef CONFIG_BOARD_MRMT_WIRELESS_ZB - udelay( 1000 ); - /* Unreset the XBee Module */ - gpio_set_value( PIN_ZB_RST_N, 1 ); -#endif -#ifdef CONFIG_BOARD_MRMT_WIRELESS_BT - udelay( 1000 ); - /* Unreset the BT Module */ - gpio_set_value( PIN_BT_RST, 0 ); -#endif - - return 0; -} -arch_initcall(mrmt1_init); - -static int __init mrmt1_early_init(void) -{ - /* To maintain power-on signal in case boot loader did not already */ - at32_select_gpio( PIN_PWR_ON, AT32_GPIOF_OUTPUT ); - gpio_request( PIN_PWR_ON, "PIN_PWR_ON" ); - gpio_direction_output( PIN_PWR_ON, 1 ); - - return 0; -} -core_initcall(mrmt1_early_init); diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c deleted file mode 100644 index afeae8978a8d..000000000000 --- a/arch/avr32/boards/atngw100/setup.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Board-specific setup code for the ATNGW100 Network Gateway - * - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/clk.h> -#include <linux/etherdevice.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/i2c.h> -#include <linux/i2c-gpio.h> -#include <linux/init.h> -#include <linux/linkage.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/leds.h> -#include <linux/spi/spi.h> -#include <linux/atmel-mci.h> -#include <linux/usb/atmel_usba_udc.h> - -#include <asm/io.h> -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -/* Oscillator frequencies. These are board-specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 20000000, /* 20 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -/* - * The ATNGW100 mkII is very similar to the ATNGW100. Both have the AT32AP7000 - * chip on board; the difference is that the ATNGW100 mkII has 128 MB 32-bit - * SDRAM (the ATNGW100 has 32 MB 16-bit SDRAM) and 256 MB 16-bit NAND flash - * (the ATNGW100 has none.) - * - * The RAM difference is handled by the boot loader, so the only difference we - * end up handling here is the NAND flash, EBI pin reservation and if LCDC or - * MACB1 should be enabled. - */ -#ifdef CONFIG_BOARD_ATNGW100_MKII -#include <linux/mtd/partitions.h> -#include <mach/smc.h> - -static struct smc_timing nand_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 10, - .ncs_write_setup = 0, - .nwe_setup = 10, - - .ncs_read_pulse = 30, - .nrd_pulse = 15, - .ncs_write_pulse = 30, - .nwe_pulse = 15, - - .read_cycle = 30, - .write_cycle = 30, - - .ncs_read_recover = 0, - .nrd_recover = 15, - .ncs_write_recover = 0, - /* WE# high -> RE# low min 60 ns */ - .nwe_recover = 50, -}; - -static struct smc_config nand_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .nwait_mode = 0, - .byte_write = 0, - .tdf_cycles = 2, - .tdf_mode = 0, -}; - -static struct mtd_partition nand_partitions[] = { - { - .name = "main", - .offset = 0x00000000, - .size = MTDPART_SIZ_FULL, - }, -}; - - -static struct atmel_nand_data atngw100mkii_nand_data __initdata = { - .cle = 21, - .ale = 22, - .rdy_pin = GPIO_PIN_PB(28), - .enable_pin = GPIO_PIN_PE(23), - .bus_width_16 = true, - .ecc_mode = NAND_ECC_SOFT, - .parts = nand_partitions, - .num_parts = ARRAY_SIZE(nand_partitions), -}; -#endif - -/* Initialized by bootloader-specific startup code. */ -struct tag *bootloader_tags __initdata; - -struct eth_addr { - u8 addr[6]; -}; -static struct eth_addr __initdata hw_addr[2]; -static struct macb_platform_data __initdata eth_data[2]; - -static struct spi_board_info spi0_board_info[] __initdata = { - { - .modalias = "mtd_dataflash", - .max_speed_hz = 8000000, - .chip_select = 0, - }, -}; - -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, -#if defined(CONFIG_BOARD_ATNGW100_MKII) - .detect_pin = GPIO_PIN_PC(25), - .wp_pin = GPIO_PIN_PE(22), -#else - .detect_pin = GPIO_PIN_PC(25), - .wp_pin = GPIO_PIN_PE(0), -#endif - }, -}; - -static struct usba_platform_data atngw100_usba_data __initdata = { -#if defined(CONFIG_BOARD_ATNGW100_MKII) - .vbus_pin = GPIO_PIN_PE(26), -#else - .vbus_pin = -ENODEV, -#endif -}; - -/* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid - * ethernet address. But we need to keep it around for a while until - * we can be reasonably sure the boot loader does this. - * - * The phy_id is ignored as the driver will probe for it. - */ -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i; - - i = tag->u.ethernet.mac_index; - if (i < ARRAY_SIZE(hw_addr)) - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - if (!is_valid_ether_addr(addr)) - return; - - /* - * Since this is board-specific code, we'll cheat and use the - * physical address directly as we happen to know that it's - * the same as the virtual address. - */ - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) - return; - - clk_enable(pclk); - __raw_writel((addr[3] << 24) | (addr[2] << 16) - | (addr[1] << 8) | addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - clk_disable(pclk); - clk_put(pclk); -} - -void __init setup_board(void) -{ - at32_map_usart(1, 0, 0); /* USART 1: /dev/ttyS0, DB9 */ - at32_setup_serial_console(0); -} - -static const struct gpio_led ngw_leds[] = { - { .name = "sys", .gpio = GPIO_PIN_PA(16), .active_low = 1, - .default_trigger = "heartbeat", - }, - { .name = "a", .gpio = GPIO_PIN_PA(19), .active_low = 1, }, - { .name = "b", .gpio = GPIO_PIN_PE(19), .active_low = 1, }, -}; - -static const struct gpio_led_platform_data ngw_led_data = { - .num_leds = ARRAY_SIZE(ngw_leds), - .leds = (void *) ngw_leds, -}; - -static struct platform_device ngw_gpio_leds = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = (void *) &ngw_led_data, - } -}; - -static struct i2c_gpio_platform_data i2c_gpio_data = { - .sda_pin = GPIO_PIN_PA(6), - .scl_pin = GPIO_PIN_PA(7), - .sda_is_open_drain = 1, - .scl_is_open_drain = 1, - .udelay = 2, /* close to 100 kHz */ -}; - -static struct platform_device i2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, - .dev = { - .platform_data = &i2c_gpio_data, - }, -}; - -static struct i2c_board_info __initdata i2c_info[] = { - /* NOTE: original ATtiny24 firmware is at address 0x0b */ -}; - -static int __init atngw100_init(void) -{ - unsigned i; - - /* - * ATNGW100 mkII uses 32-bit SDRAM interface. Reserve the - * SDRAM-specific pins so that nobody messes with them. - */ -#ifdef CONFIG_BOARD_ATNGW100_MKII - at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL); - - smc_set_timing(&nand_config, &nand_timing); - smc_set_configuration(3, &nand_config); - at32_add_device_nand(0, &atngw100mkii_nand_data); -#endif - - at32_add_device_usart(0); - - set_hw_addr(at32_add_device_eth(0, ð_data[0])); -#ifndef CONFIG_BOARD_ATNGW100_MKII_LCD - set_hw_addr(at32_add_device_eth(1, ð_data[1])); -#endif - - at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); - at32_add_device_mci(0, &mci0_data); - at32_add_device_usba(0, &atngw100_usba_data); - - for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) { - at32_select_gpio(ngw_leds[i].gpio, - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - } - platform_device_register(&ngw_gpio_leds); - - /* all these i2c/smbus pins should have external pullups for - * open-drain sharing among all I2C devices. SDA and SCL do; - * PB28/EXTINT3 (ATNGW100) and PE21 (ATNGW100 mkII) doesn't; it should - * be SMBALERT# (for PMBus), but it's not available off-board. - */ -#ifdef CONFIG_BOARD_ATNGW100_MKII - at32_select_periph(GPIO_PIOE_BASE, 1 << 21, 0, AT32_GPIOF_PULLUP); -#else - at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP); -#endif - at32_select_gpio(i2c_gpio_data.sda_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(i2c_gpio_data.scl_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - platform_device_register(&i2c_gpio_device); - i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); - - return 0; -} -postcore_initcall(atngw100_init); - -static int __init atngw100_arch_init(void) -{ - /* PB30 (ATNGW100) and PE30 (ATNGW100 mkII) is the otherwise unused - * jumper on the mainboard, with an external pullup; the jumper grounds - * it. Use it however you like, including letting U-Boot or Linux tweak - * boot sequences. - */ -#ifdef CONFIG_BOARD_ATNGW100_MKII - at32_select_gpio(GPIO_PIN_PE(30), 0); - gpio_request(GPIO_PIN_PE(30), "j15"); - gpio_direction_input(GPIO_PIN_PE(30)); - gpio_export(GPIO_PIN_PE(30), false); -#else - at32_select_gpio(GPIO_PIN_PB(30), 0); - gpio_request(GPIO_PIN_PB(30), "j15"); - gpio_direction_input(GPIO_PIN_PB(30)); - gpio_export(GPIO_PIN_PB(30), false); -#endif - - /* set_irq_type() after the arch_initcall for EIC has run, and - * before the I2C subsystem could try using this IRQ. - */ - return irq_set_irq_type(AT32_EXTINT(3), IRQ_TYPE_EDGE_FALLING); -} -arch_initcall(atngw100_arch_init); diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig deleted file mode 100644 index 8dc48214f0b7..000000000000 --- a/arch/avr32/boards/atstk1000/Kconfig +++ /dev/null @@ -1,109 +0,0 @@ -# STK1000 customization - -if BOARD_ATSTK1000 - -choice - prompt "ATSTK1000 CPU daughterboard type" - default BOARD_ATSTK1002 - -config BOARD_ATSTK1002 - bool "ATSTK1002" - select CPU_AT32AP7000 - -config BOARD_ATSTK1003 - bool "ATSTK1003" - select CPU_AT32AP7001 - -config BOARD_ATSTK1004 - bool "ATSTK1004" - select CPU_AT32AP7002 - -config BOARD_ATSTK1006 - bool "ATSTK1006" - select CPU_AT32AP7000 - -endchoice - - -config BOARD_ATSTK100X_CUSTOM - bool "Non-default STK1002/STK1003/STK1004 jumper settings" - help - You will normally leave the jumpers on the CPU card at their - default settings. If you need to use certain peripherals, - you will need to change some of those jumpers. - -if BOARD_ATSTK100X_CUSTOM - -config BOARD_ATSTK100X_SW1_CUSTOM - bool "SW1: use SSC1 (not SPI0)" - help - This also prevents using the external DAC as an audio interface, - and means you can't initialize the on-board QVGA display. - -config BOARD_ATSTK100X_SW2_CUSTOM - bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)" - help - If you change this you'll want an updated boot loader putting - the console on UART-C not UART-A. - -config BOARD_ATSTK100X_SW3_CUSTOM - bool "SW3: use TIMER1 (not SSC0 and GCLK)" - help - This also prevents using the external DAC as an audio interface. - -config BOARD_ATSTK100X_SW4_CUSTOM - bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)" - help - To use the camera interface you'll need a custom card (on the - PCI-format connector) connect a video sensor. - -config BOARD_ATSTK1002_SW5_CUSTOM - bool "SW5: use MACB1 (not LCDC)" - depends on BOARD_ATSTK1002 - -config BOARD_ATSTK1002_SW6_CUSTOM - bool "SW6: more GPIOs (not MACB0)" - depends on BOARD_ATSTK1002 - -endif # custom - -config BOARD_ATSTK100X_SPI1 - bool "Configure SPI1 controller" - depends on !BOARD_ATSTK100X_SW4_CUSTOM - help - All the signals for the second SPI controller are available on - GPIO lines and accessed through the J1 jumper block. Say "y" - here to configure that SPI controller. - -config BOARD_ATSTK1000_J2_LED - bool - default BOARD_ATSTK1000_J2_LED8 || BOARD_ATSTK1000_J2_RGB - -choice - prompt "LEDs connected to J2:" - depends on LEDS_GPIO && !BOARD_ATSTK100X_SW4_CUSTOM - optional - help - Select this if you have jumpered the J2 jumper block to the - LED0..LED7 amber leds, or to the RGB leds, using a ten-pin - IDC cable. A default "heartbeat" trigger is provided, but - you can of course override this. - -config BOARD_ATSTK1000_J2_LED8 - bool "LED0..LED7" - help - Select this if J2 is jumpered to LED0..LED7 amber leds. - -config BOARD_ATSTK1000_J2_RGB - bool "RGB leds" - help - Select this if J2 is jumpered to the RGB leds. - -endchoice - -config BOARD_ATSTK1000_EXTDAC - bool - depends on !BOARD_ATSTK100X_SW1_CUSTOM && !BOARD_ATSTK100X_SW3_CUSTOM - default y - -endif # stk 1000 diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile deleted file mode 100644 index edecee03742d..000000000000 --- a/arch/avr32/boards/atstk1000/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-y += setup.o flash.o -obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o -obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o -obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o -obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h deleted file mode 100644 index 653cc09e536c..000000000000 --- a/arch/avr32/boards/atstk1000/atstk1000.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * ATSTK1000 setup code: Daughterboard interface - * - * Copyright (C) 2007 Atmel Corporation - * - * 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 __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H -#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H - -extern struct atmel_lcdfb_pdata atstk1000_lcdc_data; - -void atstk1000_setup_j2_leds(void); - -#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */ diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c deleted file mode 100644 index 6c80aba7bf96..000000000000 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * ATSTK1002/ATSTK1006 daughterboard-specific init code - * - * Copyright (C) 2005-2007 Atmel Corporation - * - * 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/clk.h> -#include <linux/etherdevice.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/spi/spi.h> -#include <linux/spi/at73c213.h> -#include <linux/atmel-mci.h> - -#include <video/atmel_lcdc.h> - -#include <asm/io.h> -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -#include "atstk1000.h" - -/* Oscillator frequencies. These are board specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 20000000, /* 20 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -/* - * The ATSTK1006 daughterboard is very similar to the ATSTK1002. Both - * have the AT32AP7000 chip on board; the difference is that the - * STK1006 has 128 MB SDRAM (the STK1002 uses the 8 MB SDRAM chip on - * the STK1000 motherboard) and 256 MB NAND flash (the STK1002 has - * none.) - * - * The RAM difference is handled by the boot loader, so the only - * difference we end up handling here is the NAND flash. - */ -#ifdef CONFIG_BOARD_ATSTK1006 -#include <linux/mtd/partitions.h> -#include <mach/smc.h> - -static struct smc_timing nand_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 10, - .ncs_write_setup = 0, - .nwe_setup = 10, - - .ncs_read_pulse = 30, - .nrd_pulse = 15, - .ncs_write_pulse = 30, - .nwe_pulse = 15, - - .read_cycle = 30, - .write_cycle = 30, - - .ncs_read_recover = 0, - .nrd_recover = 15, - .ncs_write_recover = 0, - /* WE# high -> RE# low min 60 ns */ - .nwe_recover = 50, -}; - -static struct smc_config nand_config __initdata = { - .bus_width = 1, - .nrd_controlled = 1, - .nwe_controlled = 1, - .nwait_mode = 0, - .byte_write = 0, - .tdf_cycles = 2, - .tdf_mode = 0, -}; - -static struct mtd_partition nand_partitions[] = { - { - .name = "main", - .offset = 0x00000000, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct atmel_nand_data atstk1006_nand_data __initdata = { - .cle = 21, - .ale = 22, - .rdy_pin = GPIO_PIN_PB(30), - .enable_pin = GPIO_PIN_PB(29), - .ecc_mode = NAND_ECC_SOFT, - .parts = nand_partitions, - .num_parts = ARRAY_SIZE(nand_partitions), -}; -#endif - -struct eth_addr { - u8 addr[6]; -}; - -static struct eth_addr __initdata hw_addr[2]; -static struct macb_platform_data __initdata eth_data[2] = { - { - /* - * The MDIO pullups on STK1000 are a bit too weak for - * the autodetection to work properly, so we have to - * mask out everything but the correct address. - */ - .phy_mask = ~(1U << 16), - }, - { - .phy_mask = ~(1U << 17), - }, -}; - -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC -static struct at73c213_board_info at73c213_data = { - .ssc_id = 0, - .shortname = "AVR32 STK1000 external DAC", -}; -#endif - -#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM -static struct spi_board_info spi0_board_info[] __initdata = { -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC - { - /* AT73C213 */ - .modalias = "at73c213", - .max_speed_hz = 200000, - .chip_select = 0, - .mode = SPI_MODE_1, - .platform_data = &at73c213_data, - }, -#endif - { - /* QVGA display */ - .modalias = "ltv350qv", - .max_speed_hz = 16000000, - .chip_select = 1, - .mode = SPI_MODE_3, - }, -}; -#endif - -#ifdef CONFIG_BOARD_ATSTK100X_SPI1 -static struct spi_board_info spi1_board_info[] __initdata = { { - /* patch in custom entries here */ -} }; -#endif - -/* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid - * ethernet address. But we need to keep it around for a while until - * we can be reasonably sure the boot loader does this. - * - * The phy_id is ignored as the driver will probe for it. - */ -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i; - - i = tag->u.ethernet.mac_index; - if (i < ARRAY_SIZE(hw_addr)) - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - if (!is_valid_ether_addr(addr)) - return; - - /* - * Since this is board-specific code, we'll cheat and use the - * physical address directly as we happen to know that it's - * the same as the virtual address. - */ - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) - return; - - clk_enable(pclk); - __raw_writel((addr[3] << 24) | (addr[2] << 16) - | (addr[1] << 8) | addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - clk_disable(pclk); - clk_put(pclk); -} - -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC -static void __init atstk1002_setup_extdac(void) -{ - struct clk *gclk; - struct clk *pll; - - gclk = clk_get(NULL, "gclk0"); - if (IS_ERR(gclk)) - goto err_gclk; - pll = clk_get(NULL, "pll0"); - if (IS_ERR(pll)) - goto err_pll; - - if (clk_set_parent(gclk, pll)) { - pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n"); - goto err_set_clk; - } - - at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); - at73c213_data.dac_clk = gclk; - -err_set_clk: - clk_put(pll); -err_pll: - clk_put(gclk); -err_gclk: - return; -} -#else -static void __init atstk1002_setup_extdac(void) -{ - -} -#endif /* CONFIG_BOARD_ATSTK1000_EXTDAC */ - -void __init setup_board(void) -{ -#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_map_usart(0, 1, 0); /* USART 0/B: /dev/ttyS1, IRDA */ -#else - at32_map_usart(1, 0, 0); /* USART 1/A: /dev/ttyS0, DB9 */ -#endif - /* USART 2/unused: expansion connector */ - at32_map_usart(3, 2, 0); /* USART 3/C: /dev/ttyS2, DB9 */ - - at32_setup_serial_console(0); -} - -#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - -/* MMC card detect requires MACB0 *NOT* be used */ -#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM - .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ - .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ -#else - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, -#endif /* SW6 for sd{cd,wp} routing */ - }, -}; - -#endif /* SW2 for MMC signal routing */ - -static int __init atstk1002_init(void) -{ - /* - * ATSTK1000 uses 32-bit SDRAM interface. Reserve the - * SDRAM-specific pins so that nobody messes with them. - */ - at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL); - -#ifdef CONFIG_BOARD_ATSTK1006 - smc_set_timing(&nand_config, &nand_timing); - smc_set_configuration(3, &nand_config); - at32_add_device_nand(0, &atstk1006_nand_data); -#endif - -#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_usart(1); -#else - at32_add_device_usart(0); -#endif - at32_add_device_usart(2); - -#ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM - set_hw_addr(at32_add_device_eth(0, ð_data[0])); -#endif -#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM - at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); -#endif -#ifdef CONFIG_BOARD_ATSTK100X_SPI1 - at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); -#endif -#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, &mci0_data); -#endif -#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM - set_hw_addr(at32_add_device_eth(1, ð_data[1])); -#else - at32_add_device_lcdc(0, &atstk1000_lcdc_data, - fbmem_start, fbmem_size, - ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); -#endif - at32_add_device_usba(0, NULL); -#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM - at32_add_device_ssc(0, ATMEL_SSC_TX); -#endif - - atstk1000_setup_j2_leds(); - atstk1002_setup_extdac(); - - return 0; -} -postcore_initcall(atstk1002_init); diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c deleted file mode 100644 index ff7e23298827..000000000000 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * ATSTK1003 daughterboard-specific init code - * - * Copyright (C) 2007 Atmel Corporation - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/string.h> -#include <linux/types.h> - -#include <linux/spi/at73c213.h> -#include <linux/spi/spi.h> -#include <linux/atmel-mci.h> - -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -#include "atstk1000.h" - -/* Oscillator frequencies. These are board specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 20000000, /* 20 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC -static struct at73c213_board_info at73c213_data = { - .ssc_id = 0, - .shortname = "AVR32 STK1000 external DAC", -}; -#endif - -#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM -static struct spi_board_info spi0_board_info[] __initdata = { -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC - { - /* AT73C213 */ - .modalias = "at73c213", - .max_speed_hz = 200000, - .chip_select = 0, - .mode = SPI_MODE_1, - .platform_data = &at73c213_data, - }, -#endif - /* - * We can control the LTV350QV LCD panel, but it isn't much - * point since we don't have an LCD controller... - */ -}; -#endif - -#ifdef CONFIG_BOARD_ATSTK100X_SPI1 -static struct spi_board_info spi1_board_info[] __initdata = { { - /* patch in custom entries here */ -} }; -#endif - -#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, - }, -}; -#endif - -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC -static void __init atstk1003_setup_extdac(void) -{ - struct clk *gclk; - struct clk *pll; - - gclk = clk_get(NULL, "gclk0"); - if (IS_ERR(gclk)) - goto err_gclk; - pll = clk_get(NULL, "pll0"); - if (IS_ERR(pll)) - goto err_pll; - - if (clk_set_parent(gclk, pll)) { - pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n"); - goto err_set_clk; - } - - at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); - at73c213_data.dac_clk = gclk; - -err_set_clk: - clk_put(pll); -err_pll: - clk_put(gclk); -err_gclk: - return; -} -#else -static void __init atstk1003_setup_extdac(void) -{ - -} -#endif /* CONFIG_BOARD_ATSTK1000_EXTDAC */ - -void __init setup_board(void) -{ -#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_map_usart(0, 1, 0); /* USART 0/B: /dev/ttyS1, IRDA */ -#else - at32_map_usart(1, 0, 0); /* USART 1/A: /dev/ttyS0, DB9 */ -#endif - /* USART 2/unused: expansion connector */ - at32_map_usart(3, 2, 0); /* USART 3/C: /dev/ttyS2, DB9 */ - - at32_setup_serial_console(0); -} - -static int __init atstk1003_init(void) -{ - /* - * ATSTK1000 uses 32-bit SDRAM interface. Reserve the - * SDRAM-specific pins so that nobody messes with them. - */ - at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL); - -#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_usart(1); -#else - at32_add_device_usart(0); -#endif - at32_add_device_usart(2); - -#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM - at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); -#endif -#ifdef CONFIG_BOARD_ATSTK100X_SPI1 - at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); -#endif -#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, &mci0_data); -#endif - at32_add_device_usba(0, NULL); -#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM - at32_add_device_ssc(0, ATMEL_SSC_TX); -#endif - - atstk1000_setup_j2_leds(); - atstk1003_setup_extdac(); - - return 0; -} -postcore_initcall(atstk1003_init); diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c deleted file mode 100644 index 69a9f0f08c6e..000000000000 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * ATSTK1003 daughterboard-specific init code - * - * Copyright (C) 2007 Atmel Corporation - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/string.h> -#include <linux/types.h> - -#include <linux/spi/at73c213.h> -#include <linux/spi/spi.h> -#include <linux/atmel-mci.h> - -#include <video/atmel_lcdc.h> - -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -#include "atstk1000.h" - -/* Oscillator frequencies. These are board specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 20000000, /* 20 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC -static struct at73c213_board_info at73c213_data = { - .ssc_id = 0, - .shortname = "AVR32 STK1000 external DAC", -}; -#endif - -#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM -static struct spi_board_info spi0_board_info[] __initdata = { -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC - { - /* AT73C213 */ - .modalias = "at73c213", - .max_speed_hz = 200000, - .chip_select = 0, - .mode = SPI_MODE_1, - .platform_data = &at73c213_data, - }, -#endif - { - /* QVGA display */ - .modalias = "ltv350qv", - .max_speed_hz = 16000000, - .chip_select = 1, - .mode = SPI_MODE_3, - }, -}; -#endif - -#ifdef CONFIG_BOARD_ATSTK100X_SPI1 -static struct spi_board_info spi1_board_info[] __initdata = { { - /* patch in custom entries here */ -} }; -#endif - -#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, - }, -}; -#endif - -#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC -static void __init atstk1004_setup_extdac(void) -{ - struct clk *gclk; - struct clk *pll; - - gclk = clk_get(NULL, "gclk0"); - if (IS_ERR(gclk)) - goto err_gclk; - pll = clk_get(NULL, "pll0"); - if (IS_ERR(pll)) - goto err_pll; - - if (clk_set_parent(gclk, pll)) { - pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n"); - goto err_set_clk; - } - - at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); - at73c213_data.dac_clk = gclk; - -err_set_clk: - clk_put(pll); -err_pll: - clk_put(gclk); -err_gclk: - return; -} -#else -static void __init atstk1004_setup_extdac(void) -{ - -} -#endif /* CONFIG_BOARD_ATSTK1000_EXTDAC */ - -void __init setup_board(void) -{ -#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_map_usart(0, 1, 0); /* USART 0/B: /dev/ttyS1, IRDA */ -#else - at32_map_usart(1, 0, 0); /* USART 1/A: /dev/ttyS0, DB9 */ -#endif - /* USART 2/unused: expansion connector */ - at32_map_usart(3, 2, 0); /* USART 3/C: /dev/ttyS2, DB9 */ - - at32_setup_serial_console(0); -} - -static int __init atstk1004_init(void) -{ -#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_usart(1); -#else - at32_add_device_usart(0); -#endif - at32_add_device_usart(2); - -#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM - at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); -#endif -#ifdef CONFIG_BOARD_ATSTK100X_SPI1 - at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); -#endif -#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, &mci0_data); -#endif - at32_add_device_lcdc(0, &atstk1000_lcdc_data, - fbmem_start, fbmem_size, - ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); - at32_add_device_usba(0, NULL); -#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM - at32_add_device_ssc(0, ATMEL_SSC_TX); -#endif - - atstk1000_setup_j2_leds(); - atstk1004_setup_extdac(); - - return 0; -} -postcore_initcall(atstk1004_init); diff --git a/arch/avr32/boards/atstk1000/flash.c b/arch/avr32/boards/atstk1000/flash.c deleted file mode 100644 index 6e4d561977ff..000000000000 --- a/arch/avr32/boards/atstk1000/flash.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ATSTK1000 board-specific flash initialization - * - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> - -#include <mach/smc.h> - -static struct smc_timing flash_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 40, - .ncs_write_setup = 0, - .nwe_setup = 10, - - .ncs_read_pulse = 80, - .nrd_pulse = 40, - .ncs_write_pulse = 65, - .nwe_pulse = 55, - - .read_cycle = 120, - .write_cycle = 120, -}; - -static struct smc_config flash_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 1, -}; - -static struct mtd_partition flash_parts[] = { - { - .name = "u-boot", - .offset = 0x00000000, - .size = 0x00020000, /* 128 KiB */ - .mask_flags = MTD_WRITEABLE, - }, - { - .name = "root", - .offset = 0x00020000, - .size = 0x007d0000, - }, - { - .name = "env", - .offset = 0x007f0000, - .size = 0x00010000, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data flash_data = { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_parts), - .parts = flash_parts, -}; - -static struct resource flash_resource = { - .start = 0x00000000, - .end = 0x007fffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device flash_device = { - .name = "physmap-flash", - .id = 0, - .resource = &flash_resource, - .num_resources = 1, - .dev = { - .platform_data = &flash_data, - }, -}; - -/* This needs to be called after the SMC has been initialized */ -static int __init atstk1000_flash_init(void) -{ - int ret; - - smc_set_timing(&flash_config, &flash_timing); - ret = smc_set_configuration(0, &flash_config); - if (ret < 0) { - printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n"); - return ret; - } - - platform_device_register(&flash_device); - - return 0; -} -device_initcall(atstk1000_flash_init); diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c deleted file mode 100644 index b6b88f5e0b43..000000000000 --- a/arch/avr32/boards/atstk1000/setup.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ATSTK1000 board-specific setup code. - * - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/bootmem.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/linkage.h> - -#include <video/atmel_lcdc.h> - -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/portmux.h> - -#include "atstk1000.h" - -/* Initialized by bootloader-specific startup code. */ -struct tag *bootloader_tags __initdata; - -static struct fb_videomode __initdata ltv350qv_modes[] = { - { - .name = "320x240 @ 75", - .refresh = 75, - .xres = 320, .yres = 240, - .pixclock = KHZ2PICOS(6891), - - .left_margin = 17, .right_margin = 33, - .upper_margin = 10, .lower_margin = 10, - .hsync_len = 16, .vsync_len = 1, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata atstk1000_default_monspecs = { - .manufacturer = "SNG", - .monitor = "LTV350QV", - .modedb = ltv350qv_modes, - .modedb_len = ARRAY_SIZE(ltv350qv_modes), - .hfmin = 14820, - .hfmax = 22230, - .vfmin = 60, - .vfmax = 90, - .dclkmax = 30000000, -}; - -struct atmel_lcdfb_pdata __initdata atstk1000_lcdc_data = { - .default_bpp = 24, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_INVCLK - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &atstk1000_default_monspecs, - .guard_time = 2, -}; - -#ifdef CONFIG_BOARD_ATSTK1000_J2_LED -#include <linux/leds.h> - -static struct gpio_led stk1000_j2_led[] = { -#ifdef CONFIG_BOARD_ATSTK1000_J2_LED8 -#define LEDSTRING "J2 jumpered to LED8" - { .name = "led0:amber", .gpio = GPIO_PIN_PB( 8), }, - { .name = "led1:amber", .gpio = GPIO_PIN_PB( 9), }, - { .name = "led2:amber", .gpio = GPIO_PIN_PB(10), }, - { .name = "led3:amber", .gpio = GPIO_PIN_PB(13), }, - { .name = "led4:amber", .gpio = GPIO_PIN_PB(14), }, - { .name = "led5:amber", .gpio = GPIO_PIN_PB(15), }, - { .name = "led6:amber", .gpio = GPIO_PIN_PB(16), }, - { .name = "led7:amber", .gpio = GPIO_PIN_PB(30), - .default_trigger = "heartbeat", }, -#else /* RGB */ -#define LEDSTRING "J2 jumpered to RGB LEDs" - { .name = "r1:red", .gpio = GPIO_PIN_PB( 8), }, - { .name = "g1:green", .gpio = GPIO_PIN_PB(10), }, - { .name = "b1:blue", .gpio = GPIO_PIN_PB(14), }, - - { .name = "r2:red", .gpio = GPIO_PIN_PB( 9), - .default_trigger = "heartbeat", }, - { .name = "g2:green", .gpio = GPIO_PIN_PB(13), }, - { .name = "b2:blue", .gpio = GPIO_PIN_PB(15), - .default_trigger = "heartbeat", }, - /* PB16, PB30 unused */ -#endif -}; - -static struct gpio_led_platform_data stk1000_j2_led_data = { - .num_leds = ARRAY_SIZE(stk1000_j2_led), - .leds = stk1000_j2_led, -}; - -static struct platform_device stk1000_j2_led_dev = { - .name = "leds-gpio", - .id = 2, /* gpio block J2 */ - .dev = { - .platform_data = &stk1000_j2_led_data, - }, -}; - -void __init atstk1000_setup_j2_leds(void) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(stk1000_j2_led); i++) - at32_select_gpio(stk1000_j2_led[i].gpio, AT32_GPIOF_OUTPUT); - - printk("STK1000: " LEDSTRING "\n"); - platform_device_register(&stk1000_j2_led_dev); -} -#else /* CONFIG_BOARD_ATSTK1000_J2_LED */ -void __init atstk1000_setup_j2_leds(void) -{ - -} -#endif /* CONFIG_BOARD_ATSTK1000_J2_LED */ diff --git a/arch/avr32/boards/favr-32/Kconfig b/arch/avr32/boards/favr-32/Kconfig deleted file mode 100644 index 2c83d1ddcaec..000000000000 --- a/arch/avr32/boards/favr-32/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -# Favr-32 customization - -if BOARD_FAVR_32 - -config BOARD_FAVR32_ABDAC_RATE - int "DAC target rate" - default 44100 - range 32000 50000 - help - Specify the target rate the internal DAC should try to match. This - will use PLL1 to generate a frequency as close as possible to this - rate. - - Must be within the range 32000 to 50000, which should be suitable to - generate most other frequencies in power of 2 steps. - - Ex: - 48000 will also suit 24000 and 12000 - 44100 will also suit 22050 and 11025 - 32000 will also suit 16000 and 8000 - -endif # BOARD_FAVR_32 diff --git a/arch/avr32/boards/favr-32/Makefile b/arch/avr32/boards/favr-32/Makefile deleted file mode 100644 index 234f21508e4b..000000000000 --- a/arch/avr32/boards/favr-32/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += setup.o flash.o diff --git a/arch/avr32/boards/favr-32/flash.c b/arch/avr32/boards/favr-32/flash.c deleted file mode 100644 index 604bbd5e41d9..000000000000 --- a/arch/avr32/boards/favr-32/flash.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Favr-32 board-specific flash initialization - * - * Copyright (C) 2008 Atmel Corporation - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> - -#include <mach/smc.h> - -static struct smc_timing flash_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 40, - .ncs_write_setup = 0, - .nwe_setup = 10, - - .ncs_read_pulse = 80, - .nrd_pulse = 40, - .ncs_write_pulse = 65, - .nwe_pulse = 55, - - .read_cycle = 120, - .write_cycle = 120, -}; - -static struct smc_config flash_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 1, -}; - -static struct mtd_partition flash_parts[] = { - { - .name = "u-boot", - .offset = 0x00000000, - .size = 0x00020000, /* 128 KiB */ - .mask_flags = MTD_WRITEABLE, - }, - { - .name = "root", - .offset = 0x00020000, - .size = 0x007d0000, - }, - { - .name = "env", - .offset = 0x007f0000, - .size = 0x00010000, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data flash_data = { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_parts), - .parts = flash_parts, -}; - -static struct resource flash_resource = { - .start = 0x00000000, - .end = 0x007fffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device flash_device = { - .name = "physmap-flash", - .id = 0, - .resource = &flash_resource, - .num_resources = 1, - .dev = { - .platform_data = &flash_data, - }, -}; - -/* This needs to be called after the SMC has been initialized */ -static int __init favr32_flash_init(void) -{ - int ret; - - smc_set_timing(&flash_config, &flash_timing); - ret = smc_set_configuration(0, &flash_config); - if (ret < 0) { - printk(KERN_ERR "Favr-32: failed to set NOR flash timing\n"); - return ret; - } - - platform_device_register(&flash_device); - - return 0; -} -device_initcall(favr32_flash_init); diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c deleted file mode 100644 index 234cb071c601..000000000000 --- a/arch/avr32/boards/favr-32/setup.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Favr-32 board-specific setup code. - * - * Copyright (C) 2008 Atmel Corporation - * - * 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/clk.h> -#include <linux/etherdevice.h> -#include <linux/bootmem.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/linkage.h> -#include <linux/gpio.h> -#include <linux/leds.h> -#include <linux/atmel-mci.h> -#include <linux/pwm.h> -#include <linux/pwm_backlight.h> -#include <linux/regulator/fixed.h> -#include <linux/regulator/machine.h> -#include <linux/spi/spi.h> -#include <linux/spi/ads7846.h> - -#include <sound/atmel-abdac.h> - -#include <video/atmel_lcdc.h> - -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/init.h> -#include <mach/board.h> -#include <mach/portmux.h> - -#define PWM_BL_CH 2 - -/* Oscillator frequencies. These are board-specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 20000000, /* 20 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -/* Initialized by bootloader-specific startup code. */ -struct tag *bootloader_tags __initdata; - -static struct atmel_abdac_pdata __initdata abdac0_data = { -}; - -struct eth_addr { - u8 addr[6]; -}; -static struct eth_addr __initdata hw_addr[1]; -static struct macb_platform_data __initdata eth_data[1] = { - { - .phy_mask = ~(1U << 1), - }, -}; - -static int ads7843_get_pendown_state(void) -{ - return !gpio_get_value(GPIO_PIN_PB(3)); -} - -static struct ads7846_platform_data ads7843_data = { - .model = 7843, - .get_pendown_state = ads7843_get_pendown_state, - .pressure_max = 255, - /* - * Values below are for debounce filtering, these can be experimented - * with further. - */ - .debounce_max = 20, - .debounce_rep = 4, - .debounce_tol = 5, - - .keep_vref_on = true, - .settle_delay_usecs = 500, - .penirq_recheck_delay_usecs = 100, -}; - -static struct spi_board_info __initdata spi1_board_info[] = { - { - /* ADS7843 touch controller */ - .modalias = "ads7846", - .max_speed_hz = 2000000, - .chip_select = 0, - .bus_num = 1, - .platform_data = &ads7843_data, - }, -}; - -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, - }, -}; - -static struct fb_videomode __initdata lb104v03_modes[] = { - { - .name = "640x480 @ 50", - .refresh = 50, - .xres = 640, .yres = 480, - .pixclock = KHZ2PICOS(25100), - - .left_margin = 90, .right_margin = 70, - .upper_margin = 30, .lower_margin = 15, - .hsync_len = 12, .vsync_len = 2, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata favr32_default_monspecs = { - .manufacturer = "LG", - .monitor = "LB104V03", - .modedb = lb104v03_modes, - .modedb_len = ARRAY_SIZE(lb104v03_modes), - .hfmin = 27273, - .hfmax = 31111, - .vfmin = 45, - .vfmax = 60, - .dclkmax = 28000000, -}; - -struct atmel_lcdfb_pdata __initdata favr32_lcdc_data = { - .default_bpp = 16, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &favr32_default_monspecs, - .guard_time = 2, -}; - -static struct gpio_led favr32_leds[] = { - { - .name = "green", - .gpio = GPIO_PIN_PE(19), - .default_trigger = "heartbeat", - .active_low = 1, - }, - { - .name = "red", - .gpio = GPIO_PIN_PE(20), - .active_low = 1, - }, -}; - -static struct gpio_led_platform_data favr32_led_data = { - .num_leds = ARRAY_SIZE(favr32_leds), - .leds = favr32_leds, -}; - -static struct platform_device favr32_led_dev = { - .name = "leds-gpio", - .id = 0, - .dev = { - .platform_data = &favr32_led_data, - }, -}; - -/* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid - * ethernet address. But we need to keep it around for a while until - * we can be reasonably sure the boot loader does this. - * - * The phy_id is ignored as the driver will probe for it. - */ -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i; - - i = tag->u.ethernet.mac_index; - if (i < ARRAY_SIZE(hw_addr)) - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - if (!is_valid_ether_addr(addr)) - return; - - /* - * Since this is board-specific code, we'll cheat and use the - * physical address directly as we happen to know that it's - * the same as the virtual address. - */ - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) - return; - - clk_enable(pclk); - __raw_writel((addr[3] << 24) | (addr[2] << 16) - | (addr[1] << 8) | addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - clk_disable(pclk); - clk_put(pclk); -} - -void __init favr32_setup_leds(void) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(favr32_leds); i++) - at32_select_gpio(favr32_leds[i].gpio, AT32_GPIOF_OUTPUT); - - platform_device_register(&favr32_led_dev); -} - -static struct pwm_lookup pwm_lookup[] = { - PWM_LOOKUP("at91sam9rl-pwm", PWM_BL_CH, "pwm-backlight.0", NULL, - 5000, PWM_POLARITY_INVERSED), -}; - -static struct regulator_consumer_supply fixed_power_consumers[] = { - REGULATOR_SUPPLY("power", "pwm-backlight.0"), -}; - -static struct platform_pwm_backlight_data pwm_bl_data = { - .enable_gpio = GPIO_PIN_PA(28), - .max_brightness = 255, - .dft_brightness = 255, - .lth_brightness = 50, -}; - -static struct platform_device pwm_bl_device = { - .name = "pwm-backlight", - .dev = { - .platform_data = &pwm_bl_data, - }, -}; - -static void __init favr32_setup_atmel_pwm_bl(void) -{ - pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup)); - regulator_register_always_on(0, "fixed", fixed_power_consumers, - ARRAY_SIZE(fixed_power_consumers), 3300000); - platform_device_register(&pwm_bl_device); - at32_select_gpio(pwm_bl_data.enable_gpio, 0); -} - -void __init setup_board(void) -{ - at32_map_usart(3, 0, 0); /* USART 3 => /dev/ttyS0 */ - at32_setup_serial_console(0); -} - -static int __init set_abdac_rate(struct platform_device *pdev) -{ - int retval; - struct clk *osc1; - struct clk *pll1; - struct clk *abdac; - - if (pdev == NULL) - return -ENXIO; - - osc1 = clk_get(NULL, "osc1"); - if (IS_ERR(osc1)) { - retval = PTR_ERR(osc1); - goto out; - } - - pll1 = clk_get(NULL, "pll1"); - if (IS_ERR(pll1)) { - retval = PTR_ERR(pll1); - goto out_osc1; - } - - abdac = clk_get(&pdev->dev, "sample_clk"); - if (IS_ERR(abdac)) { - retval = PTR_ERR(abdac); - goto out_pll1; - } - - retval = clk_set_parent(pll1, osc1); - if (retval != 0) - goto out_abdac; - - /* - * Rate is 32000 to 50000 and ABDAC oversamples 256x. Multiply, in - * power of 2, to a value above 80 MHz. Power of 2 so it is possible - * for the generic clock to divide it down again and 80 MHz is the - * lowest frequency for the PLL. - */ - retval = clk_round_rate(pll1, - CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16); - if (retval <= 0) { - retval = -EINVAL; - goto out_abdac; - } - - retval = clk_set_rate(pll1, retval); - if (retval != 0) - goto out_abdac; - - retval = clk_set_parent(abdac, pll1); - if (retval != 0) - goto out_abdac; - -out_abdac: - clk_put(abdac); -out_pll1: - clk_put(pll1); -out_osc1: - clk_put(osc1); -out: - return retval; -} - -static int __init favr32_init(void) -{ - /* - * Favr-32 uses 32-bit SDRAM interface. Reserve the SDRAM-specific - * pins so that nobody messes with them. - */ - at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL); - - at32_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */ - - at32_add_device_usart(0); - - set_hw_addr(at32_add_device_eth(0, ð_data[0])); - - spi1_board_info[0].irq = gpio_to_irq(GPIO_PIN_PB(3)); - - set_abdac_rate(at32_add_device_abdac(0, &abdac0_data)); - - at32_add_device_pwm(1 << PWM_BL_CH); - at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); - at32_add_device_mci(0, &mci0_data); - at32_add_device_usba(0, NULL); - at32_add_device_lcdc(0, &favr32_lcdc_data, fbmem_start, fbmem_size, 0); - - favr32_setup_leds(); - - favr32_setup_atmel_pwm_bl(); - - return 0; -} -postcore_initcall(favr32_init); diff --git a/arch/avr32/boards/hammerhead/Kconfig b/arch/avr32/boards/hammerhead/Kconfig deleted file mode 100644 index 5c13d785cc70..000000000000 --- a/arch/avr32/boards/hammerhead/Kconfig +++ /dev/null @@ -1,43 +0,0 @@ -# Hammerhead customization - -if BOARD_HAMMERHEAD - -config BOARD_HAMMERHEAD_USB - bool "Philips ISP116x-hcd USB support" - help - This enables USB support for Hammerheads internal ISP116x - controller from Philips. - - Choose 'Y' here if you want to have your board USB driven. - -config BOARD_HAMMERHEAD_LCD - bool "Atmel AT91/AT32 LCD support" - help - This enables LCD support for the Hammerhead board. You may - also add support for framebuffer devices (AT91/AT32 LCD Controller) - and framebuffer console support to get the most out of your LCD. - - Choose 'Y' here if you have ordered a Corona daugther board and - want to have support for your Hantronix HDA-351T-LV LCD. - -config BOARD_HAMMERHEAD_SND - bool "Atmel AC97 Sound support" - help - This enables Sound support for the Hammerhead board. You may - also go through the ALSA settings to get it working. - - Choose 'Y' here if you have ordered a Corona daugther board and - want to make your board funky. - -config BOARD_HAMMERHEAD_FPGA - bool "Hammerhead FPGA Support" - default y - help - This adds support for the Cyclone III FPGA from Altera - found on Miromico's Hammerhead board. - - Choose 'Y' here if you want to have FPGA support enabled. - You will have to choose the "Hammerhead FPGA Device Support" in - Device Drivers->Misc to be able to use FPGA functionality. - -endif # BOARD_ATNGW100 diff --git a/arch/avr32/boards/hammerhead/Makefile b/arch/avr32/boards/hammerhead/Makefile deleted file mode 100644 index c740aa116755..000000000000 --- a/arch/avr32/boards/hammerhead/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += setup.o flash.o diff --git a/arch/avr32/boards/hammerhead/flash.c b/arch/avr32/boards/hammerhead/flash.c deleted file mode 100644 index e86280ccd8fa..000000000000 --- a/arch/avr32/boards/hammerhead/flash.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Hammerhead board-specific flash initialization - * - * Copyright (C) 2008 Miromico AG - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> -#include <linux/usb/isp116x.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> - -#include <mach/portmux.h> -#include <mach/at32ap700x.h> -#include <mach/smc.h> - -#include "../../mach-at32ap/clock.h" -#include "flash.h" - - -#define HAMMERHEAD_USB_PERIPH_GCLK0 0x40000000 -#define HAMMERHEAD_USB_PERIPH_CS2 0x02000000 -#define HAMMERHEAD_USB_PERIPH_EXTINT0 0x02000000 - -#define HAMMERHEAD_FPGA_PERIPH_MOSI 0x00000002 -#define HAMMERHEAD_FPGA_PERIPH_SCK 0x00000020 -#define HAMMERHEAD_FPGA_PERIPH_EXTINT3 0x10000000 - -static struct smc_timing flash_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 40, - .ncs_write_setup = 0, - .nwe_setup = 10, - - .ncs_read_pulse = 80, - .nrd_pulse = 40, - .ncs_write_pulse = 65, - .nwe_pulse = 55, - - .read_cycle = 120, - .write_cycle = 120, -}; - -static struct smc_config flash_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 1, -}; - -static struct mtd_partition flash_parts[] = { - { - .name = "u-boot", - .offset = 0x00000000, - .size = 0x00020000, /* 128 KiB */ - .mask_flags = MTD_WRITEABLE, - }, - { - .name = "root", - .offset = 0x00020000, - .size = 0x007d0000, - }, - { - .name = "env", - .offset = 0x007f0000, - .size = 0x00010000, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data flash_data = { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_parts), - .parts = flash_parts, -}; - -static struct resource flash_resource = { - .start = 0x00000000, - .end = 0x007fffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device flash_device = { - .name = "physmap-flash", - .id = 0, - .resource = &flash_resource, - .num_resources = 1, - .dev = { .platform_data = &flash_data, }, -}; - -#ifdef CONFIG_BOARD_HAMMERHEAD_USB - -static struct smc_timing isp1160_timing __initdata = { - .ncs_read_setup = 75, - .nrd_setup = 75, - .ncs_write_setup = 75, - .nwe_setup = 75, - - - /* We use conservative timing settings, as the minimal settings aren't - stable. There may be room for tweaking. */ - .ncs_read_pulse = 75, /* min. 33ns */ - .nrd_pulse = 75, /* min. 33ns */ - .ncs_write_pulse = 75, /* min. 26ns */ - .nwe_pulse = 75, /* min. 26ns */ - - .read_cycle = 225, /* min. 143ns */ - .write_cycle = 225, /* min. 136ns */ -}; - -static struct smc_config isp1160_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 0, -}; - -/* - * The platform delay function is only used to enforce the strange - * read to write delay. This can not be configured in the SMC. All other - * timings are controlled by the SMC (see timings obove) - * So in isp116x-hcd.c we should comment out USE_PLATFORM_DELAY - */ -void isp116x_delay(struct device *dev, int delay) -{ - if (delay > 150) - ndelay(delay - 150); -} - -static struct isp116x_platform_data isp1160_data = { - .sel15Kres = 1, /* use internal downstream resistors */ - .oc_enable = 0, /* external overcurrent detection */ - .int_edge_triggered = 0, /* interrupt is level triggered */ - .int_act_high = 0, /* interrupt is active low */ - .delay = isp116x_delay, /* platform delay function */ -}; - -static struct resource isp1160_resource[] = { - { - .start = 0x08000000, - .end = 0x08000001, - .flags = IORESOURCE_MEM, - }, - { - .start = 0x08000002, - .end = 0x08000003, - .flags = IORESOURCE_MEM, - }, - { - .start = 64, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device isp1160_device = { - .name = "isp116x-hcd", - .id = 0, - .resource = isp1160_resource, - .num_resources = 3, - .dev = { - .platform_data = &isp1160_data, - }, -}; -#endif - -#ifdef CONFIG_BOARD_HAMMERHEAD_USB -static int __init hammerhead_usbh_init(void) -{ - struct clk *gclk; - struct clk *osc; - - int ret; - - /* setup smc for usbh */ - smc_set_timing(&isp1160_config, &isp1160_timing); - ret = smc_set_configuration(2, &isp1160_config); - - if (ret < 0) { - printk(KERN_ERR - "hammerhead: failed to set ISP1160 USBH timing\n"); - return ret; - } - - /* setup gclk0 to run from osc1 */ - gclk = clk_get(NULL, "gclk0"); - if (IS_ERR(gclk)) { - ret = PTR_ERR(gclk); - goto err_gclk; - } - - osc = clk_get(NULL, "osc1"); - if (IS_ERR(osc)) { - ret = PTR_ERR(osc); - goto err_osc; - } - - ret = clk_set_parent(gclk, osc); - if (ret < 0) { - pr_debug("hammerhead: failed to set osc1 for USBH clock\n"); - goto err_set_clk; - } - - /* set clock to 6MHz */ - clk_set_rate(gclk, 6000000); - - /* and enable */ - clk_enable(gclk); - - /* select GCLK0 peripheral function */ - at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0, - GPIO_PERIPH_A, 0); - - /* enable CS2 peripheral function */ - at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2, - GPIO_PERIPH_A, 0); - - /* H_WAKEUP must be driven low */ - at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT); - - /* Select EXTINT0 for PB25 */ - at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0, - GPIO_PERIPH_A, 0); - - /* register usbh device driver */ - platform_device_register(&isp1160_device); - - err_set_clk: - clk_put(osc); - err_osc: - clk_put(gclk); - err_gclk: - return ret; -} -#endif - -#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA -static struct smc_timing fpga_timing __initdata = { - .ncs_read_setup = 16, - .nrd_setup = 32, - .ncs_read_pulse = 48, - .nrd_pulse = 32, - .read_cycle = 64, - - .ncs_write_setup = 16, - .nwe_setup = 16, - .ncs_write_pulse = 32, - .nwe_pulse = 32, - .write_cycle = 64, -}; - -static struct smc_config fpga_config __initdata = { - .bus_width = 4, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 0, -}; - -static struct resource hh_fpga0_resource[] = { - { - .start = 0xffe00400, - .end = 0xffe00400 + 0x3ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 4, - .end = 4, - .flags = IORESOURCE_IRQ, - }, - { - .start = 0x0c000000, - .end = 0x0c000100, - .flags = IORESOURCE_MEM, - }, - { - .start = 67, - .end = 67, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 hh_fpga0_dma_mask = DMA_BIT_MASK(32); -static struct platform_device hh_fpga0_device = { - .name = "hh_fpga", - .id = 0, - .dev = { - .dma_mask = &hh_fpga0_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .resource = hh_fpga0_resource, - .num_resources = ARRAY_SIZE(hh_fpga0_resource), -}; - -static struct clk hh_fpga0_spi_clk = { - .name = "spi_clk", - .dev = &hh_fpga0_device.dev, - .mode = pba_clk_mode, - .get_rate = pba_clk_get_rate, - .index = 1, -}; - -struct platform_device *__init at32_add_device_hh_fpga(void) -{ - /* Select peripheral functionallity for SPI SCK and MOSI */ - at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK, - GPIO_PERIPH_B, 0); - at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI, - GPIO_PERIPH_B, 0); - - /* reserve all other needed gpio - * We have on board pull ups, so there is no need - * to enable gpio pull ups */ - /* INIT_DONE (input) */ - at32_select_gpio(GPIO_PIN_PB(0), 0); - - /* nSTATUS (input) */ - at32_select_gpio(GPIO_PIN_PB(2), 0); - - /* nCONFIG (output, low) */ - at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT); - - /* CONF_DONE (input) */ - at32_select_gpio(GPIO_PIN_PB(4), 0); - - /* Select EXTINT3 for PB28 (Interrupt from FPGA) */ - at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3, - GPIO_PERIPH_A, 0); - - /* Get our parent clock */ - hh_fpga0_spi_clk.parent = clk_get(NULL, "pba"); - clk_put(hh_fpga0_spi_clk.parent); - - /* Register clock in at32 clock tree */ - at32_clk_register(&hh_fpga0_spi_clk); - - platform_device_register(&hh_fpga0_device); - return &hh_fpga0_device; -} -#endif - -/* This needs to be called after the SMC has been initialized */ -static int __init hammerhead_flash_init(void) -{ - int ret; - - smc_set_timing(&flash_config, &flash_timing); - ret = smc_set_configuration(0, &flash_config); - - if (ret < 0) { - printk(KERN_ERR "hammerhead: failed to set NOR flash timing\n"); - return ret; - } - - platform_device_register(&flash_device); - -#ifdef CONFIG_BOARD_HAMMERHEAD_USB - hammerhead_usbh_init(); -#endif - -#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA - /* Setup SMC for FPGA interface */ - smc_set_timing(&fpga_config, &fpga_timing); - ret = smc_set_configuration(3, &fpga_config); -#endif - - - if (ret < 0) { - printk(KERN_ERR "hammerhead: failed to set FPGA timing\n"); - return ret; - } - - return 0; -} - -device_initcall(hammerhead_flash_init); diff --git a/arch/avr32/boards/hammerhead/flash.h b/arch/avr32/boards/hammerhead/flash.h deleted file mode 100644 index ea70c626587b..000000000000 --- a/arch/avr32/boards/hammerhead/flash.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __BOARDS_HAMMERHEAD_FLASH_H -#define __BOARDS_HAMMERHEAD_FLASH_H - -struct platform_device *at32_add_device_hh_fpga(void); - -#endif /* __BOARDS_HAMMERHEAD_FLASH_H */ diff --git a/arch/avr32/boards/hammerhead/setup.c b/arch/avr32/boards/hammerhead/setup.c deleted file mode 100644 index dc0e317f2ecd..000000000000 --- a/arch/avr32/boards/hammerhead/setup.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Board-specific setup code for the Miromico Hammerhead board - * - * Copyright (C) 2008 Miromico AG - * - * 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/atmel-mci.h> -#include <linux/clk.h> -#include <linux/fb.h> -#include <linux/etherdevice.h> -#include <linux/i2c.h> -#include <linux/i2c-gpio.h> -#include <linux/init.h> -#include <linux/linkage.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/spi/spi.h> - -#include <video/atmel_lcdc.h> - -#include <linux/io.h> -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -#include <sound/atmel-ac97c.h> - -#include "../../mach-at32ap/clock.h" -#include "flash.h" - -/* Oscillator frequencies. These are board-specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 25000000, /* 25MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -/* Initialized by bootloader-specific startup code. */ -struct tag *bootloader_tags __initdata; - -#ifdef CONFIG_BOARD_HAMMERHEAD_LCD -static struct fb_videomode __initdata hda350tlv_modes[] = { - { - .name = "320x240 @ 75", - .refresh = 75, - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(6891), - - .left_margin = 48, - .right_margin = 18, - .upper_margin = 18, - .lower_margin = 4, - .hsync_len = 20, - .vsync_len = 2, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = { - .manufacturer = "HAN", - .monitor = "HDA350T-LV", - .modedb = hda350tlv_modes, - .modedb_len = ARRAY_SIZE(hda350tlv_modes), - .hfmin = 14900, - .hfmax = 22350, - .vfmin = 60, - .vfmax = 90, - .dclkmax = 10000000, -}; - -struct atmel_lcdfb_pdata __initdata hammerhead_lcdc_data = { - .default_bpp = 24, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_INVCLK - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &hammerhead_hda350t_monspecs, - .guard_time = 2, -}; -#endif - -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, - }, -}; - -struct eth_addr { - u8 addr[6]; -}; - -static struct eth_addr __initdata hw_addr[1]; -static struct macb_platform_data __initdata eth_data[1]; - -/* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid - * ethernet address. But we need to keep it around for a while until - * we can be reasonably sure the boot loader does this. - * - * The phy_id is ignored as the driver will probe for it. - */ -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i = tag->u.ethernet.mac_index; - - if (i < ARRAY_SIZE(hw_addr)) - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - - if (!is_valid_ether_addr(addr)) - return; - - /* - * Since this is board-specific code, we'll cheat and use the - * physical address directly as we happen to know that it's - * the same as the virtual address. - */ - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - - if (IS_ERR(pclk)) - return; - - clk_enable(pclk); - - __raw_writel((addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | - addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - - clk_disable(pclk); - clk_put(pclk); -} - -void __init setup_board(void) -{ - at32_map_usart(1, 0, 0); /* USART 1: /dev/ttyS0, DB9 */ - at32_setup_serial_console(0); -} - -static struct i2c_gpio_platform_data i2c_gpio_data = { - .sda_pin = GPIO_PIN_PA(6), - .scl_pin = GPIO_PIN_PA(7), - .sda_is_open_drain = 1, - .scl_is_open_drain = 1, - .udelay = 2, /* close to 100 kHz */ -}; - -static struct platform_device i2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, - .dev = { .platform_data = &i2c_gpio_data, }, -}; - -static struct i2c_board_info __initdata i2c_info[] = {}; - -#ifdef CONFIG_BOARD_HAMMERHEAD_SND -static struct ac97c_platform_data ac97c_data = { - .reset_pin = GPIO_PIN_PA(16), -}; -#endif - -static int __init hammerhead_init(void) -{ - /* - * Hammerhead uses 32-bit SDRAM interface. Reserve the - * SDRAM-specific pins so that nobody messes with them. - */ - at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL); - - at32_add_device_usart(0); - - /* Reserve PB29 (GCLK3). This pin is used as clock source - * for ETH PHY (25MHz). GCLK3 setup is done by U-Boot. - */ - at32_reserve_pin(GPIO_PIOB_BASE, (1<<29)); - - /* - * Hammerhead uses only one ethernet port, so we don't set - * address of second port - */ - set_hw_addr(at32_add_device_eth(0, ð_data[0])); - -#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA - at32_add_device_hh_fpga(); -#endif - at32_add_device_mci(0, &mci0_data); - -#ifdef CONFIG_BOARD_HAMMERHEAD_USB - at32_add_device_usba(0, NULL); -#endif -#ifdef CONFIG_BOARD_HAMMERHEAD_LCD - at32_add_device_lcdc(0, &hammerhead_lcdc_data, fbmem_start, - fbmem_size, ATMEL_LCDC_PRI_24BIT); -#endif - - at32_select_gpio(i2c_gpio_data.sda_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | - AT32_GPIOF_HIGH); - at32_select_gpio(i2c_gpio_data.scl_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | - AT32_GPIOF_HIGH); - platform_device_register(&i2c_gpio_device); - i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); - -#ifdef CONFIG_BOARD_HAMMERHEAD_SND - at32_add_device_ac97c(0, &ac97c_data, AC97C_BOTH); -#endif - - /* Select the Touchscreen interrupt pin mode */ - at32_select_periph(GPIO_PIOB_BASE, 0x08000000, GPIO_PERIPH_A, 0); - - return 0; -} - -postcore_initcall(hammerhead_init); diff --git a/arch/avr32/boards/merisc/Kconfig b/arch/avr32/boards/merisc/Kconfig deleted file mode 100644 index 7e043275d5a9..000000000000 --- a/arch/avr32/boards/merisc/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -# Merisc customization - -if BOARD_MERISC - -endif # BOARD_MERISC diff --git a/arch/avr32/boards/merisc/Makefile b/arch/avr32/boards/merisc/Makefile deleted file mode 100644 index d24c78729bd1..000000000000 --- a/arch/avr32/boards/merisc/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += setup.o flash.o display.o merisc_sysfs.o diff --git a/arch/avr32/boards/merisc/display.c b/arch/avr32/boards/merisc/display.c deleted file mode 100644 index e7683ee7ed40..000000000000 --- a/arch/avr32/boards/merisc/display.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Display setup code for the Merisc board - * - * Copyright (C) 2008 Martinsson Elektronik AB - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/fb.h> -#include <video/atmel_lcdc.h> -#include <asm/setup.h> -#include <mach/board.h> -#include "merisc.h" - -static struct fb_videomode merisc_fb_videomode[] = { - { - .refresh = 44, - .xres = 640, - .yres = 480, - .left_margin = 96, - .right_margin = 96, - .upper_margin = 34, - .lower_margin = 8, - .hsync_len = 64, - .vsync_len = 64, - .name = "640x480 @ 44", - .pixclock = KHZ2PICOS(25180), - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs merisc_fb_monspecs = { - .manufacturer = "Kyo", - .monitor = "TCG075VG2AD", - .modedb = merisc_fb_videomode, - .modedb_len = ARRAY_SIZE(merisc_fb_videomode), - .hfmin = 30000, - .hfmax = 33333, - .vfmin = 60, - .vfmax = 90, - .dclkmax = 30000000, -}; - -struct atmel_lcdfb_pdata merisc_lcdc_data = { - .default_bpp = 24, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &merisc_fb_monspecs, - .guard_time = 2, -}; - -static int __init merisc_display_init(void) -{ - at32_add_device_lcdc(0, &merisc_lcdc_data, fbmem_start, - fbmem_size, 0); - - return 0; -} -device_initcall(merisc_display_init); diff --git a/arch/avr32/boards/merisc/flash.c b/arch/avr32/boards/merisc/flash.c deleted file mode 100644 index 8e856fd6f013..000000000000 --- a/arch/avr32/boards/merisc/flash.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Merisc board-specific flash initialization - * - * Copyright (C) 2008 Martinsson Elektronik AB - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> -#include <mach/smc.h> - -/* Will be translated to units of 14.3 ns, rounded up */ -static struct smc_timing flash_timing __initdata = { - .ncs_read_setup = 1 * 14, - .nrd_setup = 5 * 14, - .ncs_write_setup = 1 * 14, - .nwe_setup = 2 * 14, - - .ncs_read_pulse = 12 * 14, - .nrd_pulse = 7 * 14, - .ncs_write_pulse = 8 * 14, - .nwe_pulse = 4 * 14, - - .read_cycle = 14 * 14, - .write_cycle = 10 * 14, -}; - -static struct smc_config flash_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 1, - .tdf_cycles = 3, -}; - -static struct mtd_partition flash_0_parts[] = { - { - .name = "boot", - .offset = 0x00000000, - .size = 0x00060000, - .mask_flags = 0, - }, - { - .name = "kernel", - .offset = 0x00060000, - .size = 0x00200000, - .mask_flags = 0, - }, - { - .name = "root", - .offset = 0x00260000, - .size = MTDPART_SIZ_FULL, - .mask_flags = 0, - }, -}; - -static struct mtd_partition flash_1_parts[] = { - { - .name = "2ndflash", - .offset = 0x00000000, - .size = MTDPART_SIZ_FULL, - .mask_flags = 0, - }, -}; - -static struct physmap_flash_data flash_data[] = { - { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_0_parts), - .parts = flash_0_parts, - }, - { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_1_parts), - .parts = flash_1_parts, - } -}; - -static struct resource flash_resource[] = { - { - .start = 0x00000000, - .end = 0x03ffffff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0x04000000, - .end = 0x07ffffff, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device flash_device[] = { - { - .name = "physmap-flash", - .id = 0, - .resource = &flash_resource[0], - .num_resources = 1, - .dev = { - .platform_data = &flash_data[0], - }, - }, - { - .name = "physmap-flash", - .id = 1, - .resource = &flash_resource[1], - .num_resources = 1, - .dev = { - .platform_data = &flash_data[1], - }, - }, -}; - -static int __init merisc_flash_init(void) -{ - int ret; - smc_set_timing(&flash_config, &flash_timing); - - ret = smc_set_configuration(0, &flash_config); - if (ret < 0) { - printk(KERN_ERR "Merisc: failed to set NOR flash timing #0\n"); - return ret; - } - - ret = smc_set_configuration(4, &flash_config); - if (ret < 0) { - printk(KERN_ERR "Merisc: failed to set NOR flash timing #1\n"); - return ret; - } - - platform_device_register(&flash_device[0]); - platform_device_register(&flash_device[1]); - return 0; -} -device_initcall(merisc_flash_init); diff --git a/arch/avr32/boards/merisc/merisc.h b/arch/avr32/boards/merisc/merisc.h deleted file mode 100644 index 50ffb2f3fcbf..000000000000 --- a/arch/avr32/boards/merisc/merisc.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Merisc exports - * - * Copyright (C) 2008 Martinsson Elektronik AB - * - * 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 __ARCH_AVR32_BOARDS_MERISC_MERISC_H -#define __ARCH_AVR32_BOARDS_MERISC_MERISC_H - -const char *merisc_revision(void); -const char *merisc_model(void); - -extern struct class merisc_class; - -#endif /* __ARCH_AVR32_BOARDS_MERISC_MERISC_H */ diff --git a/arch/avr32/boards/merisc/merisc_sysfs.c b/arch/avr32/boards/merisc/merisc_sysfs.c deleted file mode 100644 index 5a252318f4bd..000000000000 --- a/arch/avr32/boards/merisc/merisc_sysfs.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Merisc sysfs exports - * - * Copyright (C) 2008 Martinsson Elektronik AB - * - * 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/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/device.h> -#include <linux/timer.h> -#include <linux/err.h> -#include <linux/ctype.h> -#include "merisc.h" - -static ssize_t merisc_model_show(struct class *class, char *buf) -{ - ssize_t ret = 0; - - sprintf(buf, "%s\n", merisc_model()); - ret = strlen(buf) + 1; - - return ret; -} - -static ssize_t merisc_revision_show(struct class *class, char *buf) -{ - ssize_t ret = 0; - - sprintf(buf, "%s\n", merisc_revision()); - ret = strlen(buf) + 1; - - return ret; -} - -static struct class_attribute merisc_class_attrs[] = { - __ATTR(model, S_IRUGO, merisc_model_show, NULL), - __ATTR(revision, S_IRUGO, merisc_revision_show, NULL), - __ATTR_NULL, -}; - -struct class merisc_class = { - .name = "merisc", - .owner = THIS_MODULE, - .class_attrs = merisc_class_attrs, -}; - -static int __init merisc_sysfs_init(void) -{ - int status; - - status = class_register(&merisc_class); - if (status < 0) - return status; - - return 0; -} - -postcore_initcall(merisc_sysfs_init); diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c deleted file mode 100644 index 718a6d7eb808..000000000000 --- a/arch/avr32/boards/merisc/setup.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Board-specific setup code for the Merisc - * - * Copyright (C) 2008 Martinsson Elektronik AB - * - * 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/clk.h> -#include <linux/etherdevice.h> -#include <linux/i2c.h> -#include <linux/i2c-gpio.h> -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/linkage.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/leds.h> -#include <linux/spi/spi.h> -#include <linux/spi/ads7846.h> -#include <linux/irq.h> -#include <linux/fb.h> -#include <linux/atmel-mci.h> -#include <linux/pwm.h> -#include <linux/leds_pwm.h> - -#include <asm/io.h> -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -#include "merisc.h" - -/* Holds the autodetected board model and revision */ -static int merisc_board_id; - -/* Initialized by bootloader-specific startup code. */ -struct tag *bootloader_tags __initdata; - -/* Oscillator frequencies. These are board specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 20000000, /* 20 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -struct eth_addr { - u8 addr[6]; -}; - -static struct eth_addr __initdata hw_addr[2]; -static struct macb_platform_data __initdata eth_data[2]; - -static int ads7846_get_pendown_state_PB26(void) -{ - return !gpio_get_value(GPIO_PIN_PB(26)); -} - -static int ads7846_get_pendown_state_PB28(void) -{ - return !gpio_get_value(GPIO_PIN_PB(28)); -} - -static struct ads7846_platform_data __initdata ads7846_data = { - .model = 7846, - .vref_delay_usecs = 100, - .vref_mv = 0, - .keep_vref_on = 0, - .settle_delay_usecs = 150, - .penirq_recheck_delay_usecs = 1, - .x_plate_ohms = 800, - .debounce_rep = 4, - .debounce_max = 10, - .debounce_tol = 50, - .get_pendown_state = ads7846_get_pendown_state_PB26, - .filter_init = NULL, - .filter = NULL, - .filter_cleanup = NULL, -}; - -static struct spi_board_info __initdata spi0_board_info[] = { - { - .modalias = "ads7846", - .max_speed_hz = 3250000, - .chip_select = 0, - .bus_num = 0, - .platform_data = &ads7846_data, - .mode = SPI_MODE_0, - }, -}; - -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = GPIO_PIN_PE(19), - .wp_pin = GPIO_PIN_PE(20), - .detect_is_active_high = true, - }, -}; - -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i; - - i = tag->u.ethernet.mac_index; - if (i < ARRAY_SIZE(hw_addr)) { - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - } - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - if (!is_valid_ether_addr(addr)) - return; - - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) - return; - - clk_enable(pclk); - __raw_writel((addr[3] << 24) | (addr[2] << 16) - | (addr[1] << 8) | addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - clk_disable(pclk); - clk_put(pclk); -} - -static struct i2c_gpio_platform_data i2c_gpio_data = { - .sda_pin = GPIO_PIN_PA(6), - .scl_pin = GPIO_PIN_PA(7), - .sda_is_open_drain = 1, - .scl_is_open_drain = 1, - .udelay = 2, -}; - -static struct platform_device i2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, - .dev = { - .platform_data = &i2c_gpio_data, - }, -}; - -static struct i2c_board_info __initdata i2c_info[] = { - { - I2C_BOARD_INFO("pcf8563", 0x51) - }, -}; - -#if IS_ENABLED(CONFIG_LEDS_PWM) -static struct pwm_lookup pwm_lookup[] = { - PWM_LOOKUP("at91sam9rl-pwm", 0, "leds_pwm", "backlight", - 5000, PWM_POLARITY_NORMAL), -}; - -static struct led_pwm pwm_leds[] = { - { - .name = "backlight", - .max_brightness = 255, - }, -}; - -static struct led_pwm_platform_data pwm_data = { - .num_leds = ARRAY_SIZE(pwm_leds), - .leds = pwm_leds, -}; - -static struct platform_device leds_pwm = { - .name = "leds_pwm", - .id = -1, - .dev = { - .platform_data = &pwm_data, - }, -}; -#endif - -const char *merisc_model(void) -{ - switch (merisc_board_id) { - case 0: - case 1: - return "500-01"; - case 2: - return "BT"; - default: - return "Unknown"; - } -} - -const char *merisc_revision(void) -{ - switch (merisc_board_id) { - case 0: - return "B"; - case 1: - return "D"; - case 2: - return "A"; - default: - return "Unknown"; - } -} - -static void detect_merisc_board_id(void) -{ - /* Board ID pins MUST be set as input or the board may be damaged */ - at32_select_gpio(GPIO_PIN_PA(24), AT32_GPIOF_PULLUP); - at32_select_gpio(GPIO_PIN_PA(25), AT32_GPIOF_PULLUP); - at32_select_gpio(GPIO_PIN_PA(26), AT32_GPIOF_PULLUP); - at32_select_gpio(GPIO_PIN_PA(27), AT32_GPIOF_PULLUP); - - merisc_board_id = !gpio_get_value(GPIO_PIN_PA(24)) + - !gpio_get_value(GPIO_PIN_PA(25)) * 2 + - !gpio_get_value(GPIO_PIN_PA(26)) * 4 + - !gpio_get_value(GPIO_PIN_PA(27)) * 8; -} - -void __init setup_board(void) -{ - at32_map_usart(0, 0, 0); - at32_map_usart(1, 1, 0); - at32_map_usart(3, 3, 0); - at32_setup_serial_console(1); -} - -static int __init merisc_init(void) -{ - detect_merisc_board_id(); - - printk(KERN_NOTICE "BOARD: Merisc %s revision %s\n", merisc_model(), - merisc_revision()); - - /* Reserve pins for SDRAM */ - at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL | (1 << 26)); - - if (merisc_board_id >= 1) - at32_map_usart(2, 2, 0); - - at32_add_device_usart(0); - at32_add_device_usart(1); - if (merisc_board_id >= 1) - at32_add_device_usart(2); - at32_add_device_usart(3); - set_hw_addr(at32_add_device_eth(0, ð_data[0])); - - /* ADS7846 PENIRQ */ - if (merisc_board_id == 0) { - ads7846_data.get_pendown_state = ads7846_get_pendown_state_PB26; - at32_select_periph(GPIO_PIOB_BASE, 1 << 26, - GPIO_PERIPH_A, AT32_GPIOF_PULLUP); - spi0_board_info[0].irq = AT32_EXTINT(1); - } else { - ads7846_data.get_pendown_state = ads7846_get_pendown_state_PB28; - at32_select_periph(GPIO_PIOB_BASE, 1 << 28, GPIO_PERIPH_A, - AT32_GPIOF_PULLUP); - spi0_board_info[0].irq = AT32_EXTINT(3); - } - - /* ADS7846 busy pin */ - at32_select_gpio(GPIO_PIN_PA(4), AT32_GPIOF_PULLUP); - - at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); - - at32_add_device_mci(0, &mci0_data); - -#if IS_ENABLED(CONFIG_LEDS_PWM) - pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup)); - at32_add_device_pwm((1 << 0) | (1 << 2)); - platform_device_register(&leds_pwm); -#else - at32_add_device_pwm((1 << 2)); -#endif - - at32_select_gpio(i2c_gpio_data.sda_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(i2c_gpio_data.scl_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - platform_device_register(&i2c_gpio_device); - - i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); - - return 0; -} -postcore_initcall(merisc_init); diff --git a/arch/avr32/boards/mimc200/Makefile b/arch/avr32/boards/mimc200/Makefile deleted file mode 100644 index c740aa116755..000000000000 --- a/arch/avr32/boards/mimc200/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += setup.o flash.o diff --git a/arch/avr32/boards/mimc200/flash.c b/arch/avr32/boards/mimc200/flash.c deleted file mode 100644 index d83d650fc13f..000000000000 --- a/arch/avr32/boards/mimc200/flash.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * MIMC200 board-specific flash initialization - * - * Copyright (C) 2008 Mercury IMC Ltd - * - * 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/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> - -#include <mach/smc.h> - -static struct smc_timing flash_timing __initdata = { - .ncs_read_setup = 0, - .nrd_setup = 15, - .ncs_write_setup = 0, - .nwe_setup = 0, - - .ncs_read_pulse = 115, - .nrd_pulse = 110, - .ncs_write_pulse = 60, - .nwe_pulse = 60, - - .read_cycle = 115, - .write_cycle = 100, -}; - -static struct smc_config flash_config __initdata = { - .bus_width = 2, - .nrd_controlled = 1, - .nwe_controlled = 1, - .byte_write = 1, -}; - -/* system flash definition */ - -static struct mtd_partition flash_parts_system[] = { - { - .name = "u-boot", - .offset = 0x00000000, - .size = 0x00020000, /* 128 KiB */ - .mask_flags = MTD_WRITEABLE, - }, - { - .name = "root", - .offset = 0x00020000, - .size = 0x007c0000, - }, - { - .name = "splash", - .offset = 0x007e0000, - .size = 0x00010000, /* 64KiB */ - }, - { - .name = "env", - .offset = 0x007f0000, - .size = 0x00010000, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data flash_system = { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_parts_system), - .parts = flash_parts_system, -}; - -static struct resource flash_resource_system = { - .start = 0x00000000, - .end = 0x007fffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device flash_device_system = { - .name = "physmap-flash", - .id = 0, - .resource = &flash_resource_system, - .num_resources = 1, - .dev = { - .platform_data = &flash_system, - }, -}; - -/* data flash definition */ - -static struct mtd_partition flash_parts_data[] = { - { - .name = "data", - .offset = 0x00000000, - .size = 0x00800000, - }, -}; - -static struct physmap_flash_data flash_data = { - .width = 2, - .nr_parts = ARRAY_SIZE(flash_parts_data), - .parts = flash_parts_data, -}; - -static struct resource flash_resource_data = { - .start = 0x08000000, - .end = 0x087fffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device flash_device_data = { - .name = "physmap-flash", - .id = 1, - .resource = &flash_resource_data, - .num_resources = 1, - .dev = { - .platform_data = &flash_data, - }, -}; - -/* This needs to be called after the SMC has been initialized */ -static int __init mimc200_flash_init(void) -{ - int ret; - - smc_set_timing(&flash_config, &flash_timing); - ret = smc_set_configuration(0, &flash_config); - if (ret < 0) { - printk(KERN_ERR "mimc200: failed to set 'System' NOR flash timing\n"); - return ret; - } - ret = smc_set_configuration(1, &flash_config); - if (ret < 0) { - printk(KERN_ERR "mimc200: failed to set 'Data' NOR flash timing\n"); - return ret; - } - - platform_device_register(&flash_device_system); - platform_device_register(&flash_device_data); - - return 0; -} -device_initcall(mimc200_flash_init); diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c deleted file mode 100644 index 1cb8e9cc5cfa..000000000000 --- a/arch/avr32/boards/mimc200/setup.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Board-specific setup code for the MIMC200 - * - * Copyright (C) 2008 Mercury IMC Ltd - * - * 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. - */ - -extern struct atmel_lcdfb_pdata mimc200_lcdc_data; - -#include <linux/clk.h> -#include <linux/etherdevice.h> -#include <linux/i2c-gpio.h> -#include <linux/init.h> -#include <linux/linkage.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/leds.h> -#include <linux/spi/spi.h> -#include <linux/spi/eeprom.h> - -#include <video/atmel_lcdc.h> -#include <linux/fb.h> - -#include <linux/atmel-mci.h> -#include <linux/io.h> -#include <asm/setup.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/init.h> -#include <mach/portmux.h> - -/* Oscillator frequencies. These are board-specific */ -unsigned long at32_board_osc_rates[3] = { - [0] = 32768, /* 32.768 kHz on RTC osc */ - [1] = 10000000, /* 10 MHz on osc0 */ - [2] = 12000000, /* 12 MHz on osc1 */ -}; - -/* Initialized by bootloader-specific startup code. */ -struct tag *bootloader_tags __initdata; - -static struct fb_videomode __initdata pt0434827_modes[] = { - { - .name = "480x272 @ 72", - .refresh = 72, - .xres = 480, .yres = 272, - .pixclock = KHZ2PICOS(10000), - - .left_margin = 1, .right_margin = 1, - .upper_margin = 12, .lower_margin = 1, - .hsync_len = 42, .vsync_len = 1, - - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, -}; - -static struct fb_monspecs __initdata mimc200_default_monspecs = { - .manufacturer = "PT", - .monitor = "PT0434827-A401", - .modedb = pt0434827_modes, - .modedb_len = ARRAY_SIZE(pt0434827_modes), - .hfmin = 14820, - .hfmax = 22230, - .vfmin = 60, - .vfmax = 85, - .dclkmax = 25200000, -}; - -struct atmel_lcdfb_pdata __initdata mimc200_lcdc_data = { - .default_bpp = 16, - .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, - .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT - | ATMEL_LCDC_INVCLK - | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE - | ATMEL_LCDC_MEMOR_BIG), - .default_monspecs = &mimc200_default_monspecs, - .guard_time = 2, -}; - -struct eth_addr { - u8 addr[6]; -}; -static struct eth_addr __initdata hw_addr[2]; -static struct macb_platform_data __initdata eth_data[2]; - -static struct spi_eeprom eeprom_25lc010 = { - .name = "25lc010", - .byte_len = 128, - .page_size = 16, - .flags = EE_ADDR1, -}; - -static struct spi_board_info spi0_board_info[] __initdata = { - { - .modalias = "rtc-ds1390", - .max_speed_hz = 4000000, - .chip_select = 2, - }, - { - .modalias = "at25", - .max_speed_hz = 1000000, - .chip_select = 1, - .mode = SPI_MODE_3, - .platform_data = &eeprom_25lc010, - }, -}; - -static struct mci_platform_data __initdata mci0_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = GPIO_PIN_PA(26), - .wp_pin = GPIO_PIN_PA(27), - }, -}; - -/* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid - * ethernet address. But we need to keep it around for a while until - * we can be reasonably sure the boot loader does this. - * - * The phy_id is ignored as the driver will probe for it. - */ -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i; - - i = tag->u.ethernet.mac_index; - if (i < ARRAY_SIZE(hw_addr)) - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - if (!is_valid_ether_addr(addr)) - return; - - /* - * Since this is board-specific code, we'll cheat and use the - * physical address directly as we happen to know that it's - * the same as the virtual address. - */ - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) - return; - - clk_enable(pclk); - __raw_writel((addr[3] << 24) | (addr[2] << 16) - | (addr[1] << 8) | addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - clk_disable(pclk); - clk_put(pclk); -} - -void __init setup_board(void) -{ - at32_map_usart(0, 0, 0); /* USART 0: /dev/ttyS0 (TTL --> Altera) */ - at32_map_usart(1, 1, 0); /* USART 1: /dev/ttyS1 (RS232) */ - at32_map_usart(2, 2, 0); /* USART 2: /dev/ttyS2 (RS485) */ - at32_map_usart(3, 3, 0); /* USART 3: /dev/ttyS3 (RS422 Multidrop) */ -} - -static struct i2c_gpio_platform_data i2c_gpio_data = { - .sda_pin = GPIO_PIN_PA(6), - .scl_pin = GPIO_PIN_PA(7), - .sda_is_open_drain = 1, - .scl_is_open_drain = 1, - .udelay = 2, /* close to 100 kHz */ -}; - -static struct platform_device i2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, - .dev = { - .platform_data = &i2c_gpio_data, - }, -}; - -static struct i2c_board_info __initdata i2c_info[] = { -}; - -static int __init mimc200_init(void) -{ - /* - * MIMC200 uses 16-bit SDRAM interface, so we don't need to - * reserve any pins for it. - */ - - at32_add_device_usart(0); - at32_add_device_usart(1); - at32_add_device_usart(2); - at32_add_device_usart(3); - - set_hw_addr(at32_add_device_eth(0, ð_data[0])); - set_hw_addr(at32_add_device_eth(1, ð_data[1])); - - at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); - at32_add_device_mci(0, &mci0_data); - at32_add_device_usba(0, NULL); - - at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP); - at32_select_gpio(i2c_gpio_data.sda_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(i2c_gpio_data.scl_pin, - AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - platform_device_register(&i2c_gpio_device); - i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); - - at32_add_device_lcdc(0, &mimc200_lcdc_data, - fbmem_start, fbmem_size, - ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_CONTROL | ATMEL_LCDC_ALT_24B_DATA); - - return 0; -} -postcore_initcall(mimc200_init); diff --git a/arch/avr32/boot/images/.gitignore b/arch/avr32/boot/images/.gitignore deleted file mode 100644 index 64ea9d0141d2..000000000000 --- a/arch/avr32/boot/images/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -uImage -uImage.srec -vmlinux.cso -sfdwarf.log diff --git a/arch/avr32/boot/images/Makefile b/arch/avr32/boot/images/Makefile deleted file mode 100644 index 2a3b53978a3b..000000000000 --- a/arch/avr32/boot/images/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (C) 2004-2006 Atmel Corporation -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# - -extra-y := vmlinux.bin vmlinux.gz - -OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note.gnu.build-id -$(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE - $(call if_changed,gzip) - -UIMAGE_LOADADDR = $(CONFIG_LOAD_ADDRESS) -UIMAGE_ENTRYADDR = $(CONFIG_ENTRY_ADDRESS) -UIMAGE_COMPRESSION = gzip - -targets += uImage uImage.srec -$(obj)/uImage: $(obj)/vmlinux.gz - $(call if_changed,uimage) - @echo ' Image $@ is ready' - -OBJCOPYFLAGS_uImage.srec := -I binary -O srec -$(obj)/uImage.srec: $(obj)/uImage - $(call if_changed,objcopy) - -OBJCOPYFLAGS_vmlinux.elf := --change-section-lma .text-0x80000000 \ - --change-section-lma __ex_table-0x80000000 \ - --change-section-lma .rodata-0x80000000 \ - --change-section-lma .data-0x80000000 \ - --change-section-lma .init-0x80000000 \ - --change-section-lma .bss-0x80000000 \ - --change-section-lma __param-0x80000000 \ - --change-section-lma __ksymtab-0x80000000 \ - --change-section-lma __ksymtab_gpl-0x80000000 \ - --change-section-lma __kcrctab-0x80000000 \ - --change-section-lma __kcrctab_gpl-0x80000000 \ - --change-section-lma __ksymtab_strings-0x80000000 \ - --set-start 0xa0000000 -$(obj)/vmlinux.elf: vmlinux FORCE - $(call if_changed,objcopy) - -quiet_cmd_sfdwarf = SFDWARF $@ - cmd_sfdwarf = sfdwarf $< TO $@ GNUAVR IW $(SFDWARF_FLAGS) > $(obj)/sfdwarf.log - -$(obj)/vmlinux.cso: $(obj)/vmlinux.elf FORCE - $(call if_changed,sfdwarf) - -install: $(BOOTIMAGE) - sh $(srctree)/install-kernel.sh $< - -# Generated files to be removed upon make clean -clean-files := vmlinux.elf vmlinux.bin vmlinux.gz uImage uImage.srec diff --git a/arch/avr32/boot/u-boot/Makefile b/arch/avr32/boot/u-boot/Makefile deleted file mode 100644 index 125ddc96c275..000000000000 --- a/arch/avr32/boot/u-boot/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -extra-y := head.o - -obj-y := empty.o diff --git a/arch/avr32/boot/u-boot/empty.S b/arch/avr32/boot/u-boot/empty.S deleted file mode 100644 index 8ac91a5f12f0..000000000000 --- a/arch/avr32/boot/u-boot/empty.S +++ /dev/null @@ -1 +0,0 @@ -/* Empty file */ diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S deleted file mode 100644 index 2ffc298f061b..000000000000 --- a/arch/avr32/boot/u-boot/head.S +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Startup code for use with the u-boot bootloader. - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 <asm/setup.h> -#include <asm/thread_info.h> -#include <asm/sysreg.h> - - /* - * The kernel is loaded where we want it to be and all caches - * have just been flushed. We get two parameters from u-boot: - * - * r12 contains a magic number (ATAG_MAGIC) - * r11 points to a tag table providing information about - * the system. - */ - .section .init.text,"ax" - .global _start -_start: - /* Initialize .bss */ - lddpc r2, bss_start_addr - lddpc r3, end_addr - mov r0, 0 - mov r1, 0 -1: st.d r2++, r0 - cp r2, r3 - brlo 1b - - /* Initialize status register */ - lddpc r0, init_sr - mtsr SYSREG_SR, r0 - - /* Set initial stack pointer */ - lddpc sp, stack_addr - sub sp, -THREAD_SIZE - -#ifdef CONFIG_FRAME_POINTER - /* Mark last stack frame */ - mov lr, 0 - mov r7, 0 -#endif - - /* Check if the boot loader actually provided a tag table */ - lddpc r0, magic_number - cp.w r12, r0 - brne no_tag_table - - /* - * Save the tag table address for later use. This must be done - * _after_ .bss has been initialized... - */ - lddpc r0, tag_table_addr - st.w r0[0], r11 - - /* Jump to loader-independent setup code */ - rjmp kernel_entry - - .align 2 -magic_number: - .long ATAG_MAGIC -tag_table_addr: - .long bootloader_tags -bss_start_addr: - .long __bss_start -end_addr: - .long _end -init_sr: - .long 0x007f0000 /* Supervisor mode, everything masked */ -stack_addr: - .long init_thread_union -panic_addr: - .long panic - -no_tag_table: - sub r12, pc, (. - 2f) - /* branch to panic() which can be far away with that construct */ - lddpc pc, panic_addr -2: .asciz "Boot loader didn't provide correct magic number\n" diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig deleted file mode 100644 index ce0030020c25..000000000000 --- a/arch/avr32/configs/atngw100_defconfig +++ /dev/null @@ -1,142 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATNGW100_MKI=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPP_ASYNC=m -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=350 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig deleted file mode 100644 index 01ff632249c0..000000000000 --- a/arch/avr32/configs/atngw100_evklcd100_defconfig +++ /dev/null @@ -1,158 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATNGW100_MKI=y -CONFIG_BOARD_ATNGW100_EVKLCD10X=y -CONFIG_BOARD_ATNGW100_EVKLCD10X_QVGA=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPP_ASYNC=m -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_WM97XX=m -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_HRTIMER=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_DRIVERS is not set -CONFIG_SND_ATMEL_AC97C=m -# CONFIG_SND_SPI is not set -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=350 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig deleted file mode 100644 index c4021dfd5347..000000000000 --- a/arch/avr32/configs/atngw100_evklcd101_defconfig +++ /dev/null @@ -1,157 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATNGW100_MKI=y -CONFIG_BOARD_ATNGW100_EVKLCD10X=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPP_ASYNC=m -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_WM97XX=m -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_HRTIMER=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_DRIVERS is not set -CONFIG_SND_ATMEL_AC97C=m -# CONFIG_SND_SPI is not set -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=350 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig deleted file mode 100644 index ffcc28df9dbc..000000000000 --- a/arch/avr32/configs/atngw100_mrmt_defconfig +++ /dev/null @@ -1,136 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_SLUB_DEBUG is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_OWNERSHIP_TRACE is not set -# CONFIG_SUSPEND is not set -CONFIG_PM=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_SYN_COOKIES=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -CONFIG_BT=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_HIDP=m -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_NETDEVICES=y -CONFIG_MACB=y -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=m -# CONFIG_SERIO is not set -CONFIG_VT_HW_CONSOLE_BINDING=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=y -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -CONFIG_SND_ATMEL_AC97C=m -# CONFIG_SND_SPI is not set -CONFIG_USB_GADGET=m -CONFIG_USB_GADGET_DEBUG_FILES=y -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_MMC=y -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_PWM=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_S35390A=m -CONFIG_RTC_DRV_AT32AP700X=m -CONFIG_DMADEVICES=y -CONFIG_UIO=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_NTFS_FS=m -CONFIG_NTFS_RW=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_CIFS=m -CONFIG_CIFS_STATS=y -CONFIG_CIFS_WEAK_PW_HASH=y -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_UTF8=y -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_CRC_CCITT=y diff --git a/arch/avr32/configs/atngw100mkii_defconfig b/arch/avr32/configs/atngw100mkii_defconfig deleted file mode 100644 index 04962641c936..000000000000 --- a/arch/avr32/configs/atngw100mkii_defconfig +++ /dev/null @@ -1,144 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATNGW100_MKII=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPP_ASYNC=m -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=350 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig deleted file mode 100644 index 89c2cda573da..000000000000 --- a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig +++ /dev/null @@ -1,161 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATNGW100_MKII=y -CONFIG_BOARD_ATNGW100_MKII_LCD=y -CONFIG_BOARD_ATNGW100_EVKLCD10X=y -CONFIG_BOARD_ATNGW100_EVKLCD10X_QVGA=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPP_ASYNC=m -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_WM97XX=m -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_HRTIMER=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_DRIVERS is not set -CONFIG_SND_ATMEL_AC97C=m -# CONFIG_SND_SPI is not set -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=350 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig deleted file mode 100644 index 1b4d4a87a356..000000000000 --- a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig +++ /dev/null @@ -1,160 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATNGW100_MKII=y -CONFIG_BOARD_ATNGW100_MKII_LCD=y -CONFIG_BOARD_ATNGW100_EVKLCD10X=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPP_ASYNC=m -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_WM97XX=m -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_HRTIMER=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_DRIVERS is not set -CONFIG_SND_ATMEL_AC97C=m -# CONFIG_SND_SPI is not set -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=350 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig deleted file mode 100644 index 9b8b52e54b79..000000000000 --- a/arch/avr32/configs/atstk1002_defconfig +++ /dev/null @@ -1,157 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=m -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE_DEMUX=m -CONFIG_NET_IPGRE=m -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -# CONFIG_INET_LRO is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_BRIDGE=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_ATMEL_SSC=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -CONFIG_BLK_DEV_SR=m -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_ATA=m -# CONFIG_SATA_PMP is not set -CONFIG_PATA_AT32=m -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_ASYNC=m -CONFIG_INPUT=m -CONFIG_INPUT_EVDEV=m -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=m -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_GPIO=m -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_LTV350QV=y -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -CONFIG_SND_AT73C213=m -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=m -CONFIG_LEDS_PWM=m -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=m -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig deleted file mode 100644 index ccce1a0b7917..000000000000 --- a/arch/avr32/configs/atstk1003_defconfig +++ /dev/null @@ -1,137 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATSTK1003=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_ATMEL_SSC=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -CONFIG_BLK_DEV_SR=m -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_ATA=m -# CONFIG_SATA_PMP is not set -CONFIG_PATA_AT32=m -CONFIG_NETDEVICES=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_ASYNC=m -CONFIG_INPUT=m -CONFIG_INPUT_EVDEV=m -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=m -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_GPIO=m -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -# CONFIG_SND_DRIVERS is not set -CONFIG_SND_AT73C213=m -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=m -CONFIG_LEDS_PWM=m -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=m -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig deleted file mode 100644 index e64288fc794d..000000000000 --- a/arch/avr32/configs/atstk1004_defconfig +++ /dev/null @@ -1,135 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATSTK1004=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_ATMEL_SSC=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -CONFIG_BLK_DEV_SR=m -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_ATA=m -# CONFIG_SATA_PMP is not set -CONFIG_PATA_AT32=m -CONFIG_NETDEVICES=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_ASYNC=m -CONFIG_INPUT=m -CONFIG_INPUT_EVDEV=m -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=m -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_GPIO=m -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_LTV350QV=y -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=m -CONFIG_LEDS_PWM=m -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=m -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig deleted file mode 100644 index 7d669f79ff74..000000000000 --- a/arch/avr32/configs/atstk1006_defconfig +++ /dev/null @@ -1,160 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_ATSTK1006=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=m -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE_DEMUX=m -CONFIG_NET_IPGRE=m -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -# CONFIG_INET_LRO is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_BRIDGE=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_MTD_UBI=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_ATMEL_SSC=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -CONFIG_BLK_DEV_SR=m -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_ATA=m -# CONFIG_SATA_PMP is not set -CONFIG_PATA_AT32=m -CONFIG_NETDEVICES=y -CONFIG_TUN=m -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_ASYNC=m -CONFIG_INPUT=m -CONFIG_INPUT_EVDEV=m -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=m -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_GPIO=m -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_LTV350QV=y -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -CONFIG_SND_AT73C213=m -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_TEST=m -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=m -CONFIG_LEDS_PWM=m -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=m -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_CIFS=m -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DETECT_HUNG_TASK=y diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig deleted file mode 100644 index 560c52f87d45..000000000000 --- a/arch/avr32/configs/favr-32_defconfig +++ /dev/null @@ -1,143 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_FAVR_32=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=m -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_NET_IPIP=m -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -CONFIG_IPV6_SIT=m -CONFIG_IPV6_TUNNEL=m -CONFIG_BRIDGE=m -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_ATMEL_SSC=m -CONFIG_NETDEVICES=y -CONFIG_MACB=y -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_ASYNC=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_EVDEV=m -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=m -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_GPIO=m -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=m -# CONFIG_SERIO is not set -# CONFIG_CONSOLE_TRANSLATIONS is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -# CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_BACKLIGHT_PWM=m -CONFIG_SOUND=m -CONFIG_SOUND_PRIME=m -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_MMC=y -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_DMADEVICES=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -# CONFIG_JFFS2_FS_WRITEBUFFER is not set -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_DEBUG_FS=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_CRYPTO_HW is not set diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig deleted file mode 100644 index d57fadb9e6b6..000000000000 --- a/arch/avr32/configs/hammerhead_defconfig +++ /dev/null @@ -1,145 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_HAMMERHEAD=y -CONFIG_BOARD_HAMMERHEAD_USB=y -CONFIG_BOARD_HAMMERHEAD_LCD=y -CONFIG_BOARD_HAMMERHEAD_SND=y -# CONFIG_BOARD_HAMMERHEAD_FPGA is not set -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_ADVANCED is not set -CONFIG_NETFILTER_XTABLES=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_BLK_DEV_RAM=m -CONFIG_ATMEL_TCLIB=y -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_NETDEVICES=y -CONFIG_MACB=y -CONFIG_INPUT_FF_MEMLESS=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_GPIO=m -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=m -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_SEQUENCER=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_SUPPORT_OLD_API is not set -CONFIG_HID_A4TECH=m -CONFIG_HID_APPLE=m -CONFIG_HID_BELKIN=m -CONFIG_HID_CHERRY=m -CONFIG_HID_CHICONY=m -CONFIG_HID_CYPRESS=m -CONFIG_HID_EZKEY=m -CONFIG_HID_GYRATION=m -CONFIG_HID_LOGITECH=m -CONFIG_HID_MICROSOFT=m -CONFIG_HID_MONTEREY=m -CONFIG_HID_PANTHERLORD=m -CONFIG_HID_PETALYNX=m -CONFIG_HID_SAMSUNG=m -CONFIG_HID_SUNPLUS=m -CONFIG_USB=m -CONFIG_USB_MON=m -CONFIG_USB_ISP116X_HCD=m -CONFIG_USB_STORAGE=m -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_MMC=m -CONFIG_MMC_ATMELMCI=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT32AP700X=y -CONFIG_EXT2_FS=m -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_UTF8=m -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_CCITT=m -CONFIG_CRC_ITU_T=m -CONFIG_CRC7=m diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig deleted file mode 100644 index e6a9cb7d574e..000000000000 --- a/arch/avr32/configs/merisc_defconfig +++ /dev/null @@ -1,115 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_MERISC=y -CONFIG_AP700X_32_BIT_SMC=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -CONFIG_CAN=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_ABSENT=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_BLOCK2MTD=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_ATMEL_SSC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_NETDEVICES=y -CONFIG_MACB=y -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_UINPUT=y -# CONFIG_SERIO is not set -# CONFIG_CONSOLE_TRANSLATIONS is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=y -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -# CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_LOGO=y -CONFIG_MMC=y -CONFIG_MMC_ATMELMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_PWM=y -CONFIG_RTC_CLASS=y -# CONFIG_RTC_HCTOSYS is not set -CONFIG_RTC_DRV_PCF8563=y -CONFIG_DMADEVICES=y -CONFIG_UIO=y -CONFIG_PWM=y -CONFIG_PWM_ATMEL=m -CONFIG_EXT2_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_WBUF_VERIFY=y -CONFIG_CRAMFS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_UTF8=y -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_HW is not set diff --git a/arch/avr32/configs/mimc200_defconfig b/arch/avr32/configs/mimc200_defconfig deleted file mode 100644 index 49c7e890af7b..000000000000 --- a/arch/avr32/configs/mimc200_defconfig +++ /dev/null @@ -1,114 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_BASE_FULL is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_BOARD_MIMC200=y -# CONFIG_OWNERSHIP_TRACE is not set -CONFIG_NMI_DEBUGGING=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_AVR32_AT32AP_CPUFREQ=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_LRO is not set -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_ATMEL_TCLIB=y -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_AT25=y -CONFIG_NETDEVICES=y -CONFIG_MACB=y -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_AT32AP700X_WDT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -# CONFIG_USB_SUPPORT is not set -CONFIG_MMC=y -CONFIG_MMC_TEST=y -CONFIG_MMC_ATMELMCI=y -CONFIG_MMC_SPI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_DS1390=y -CONFIG_DMADEVICES=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=850 -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -CONFIG_JFFS2_FS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_UTF8=y -CONFIG_FRAME_POINTER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRC_CCITT=y diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild deleted file mode 100644 index 3d7ef2c17a7c..000000000000 --- a/arch/avr32/include/asm/Kbuild +++ /dev/null @@ -1,23 +0,0 @@ - -generic-y += clkdev.h -generic-y += delay.h -generic-y += device.h -generic-y += div64.h -generic-y += emergency-restart.h -generic-y += exec.h -generic-y += futex.h -generic-y += irq_regs.h -generic-y += irq_work.h -generic-y += local.h -generic-y += local64.h -generic-y += mcs_spinlock.h -generic-y += mm-arch-hooks.h -generic-y += param.h -generic-y += percpu.h -generic-y += preempt.h -generic-y += sections.h -generic-y += topology.h -generic-y += trace_clock.h -generic-y += vga.h -generic-y += word-at-a-time.h -generic-y += xor.h diff --git a/arch/avr32/include/asm/addrspace.h b/arch/avr32/include/asm/addrspace.h deleted file mode 100644 index 5a47a7979648..000000000000 --- a/arch/avr32/include/asm/addrspace.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Definitions for the address spaces of the AVR32 CPUs. Heavily based on - * include/asm-sh/addrspace.h - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_ADDRSPACE_H -#define __ASM_AVR32_ADDRSPACE_H - -#ifdef CONFIG_MMU - -/* Memory segments when segmentation is enabled */ -#define P0SEG 0x00000000 -#define P1SEG 0x80000000 -#define P2SEG 0xa0000000 -#define P3SEG 0xc0000000 -#define P4SEG 0xe0000000 - -/* Returns the privileged segment base of a given address */ -#define PXSEG(a) (((unsigned long)(a)) & 0xe0000000) - -/* Returns the physical address of a PnSEG (n=1,2) address */ -#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) - -/* - * Map an address to a certain privileged segment - */ -#define P1SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ - | P1SEG)) -#define P2SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ - | P2SEG)) -#define P3SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ - | P3SEG)) -#define P4SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ - | P4SEG)) - -#endif /* CONFIG_MMU */ - -#endif /* __ASM_AVR32_ADDRSPACE_H */ diff --git a/arch/avr32/include/asm/asm-offsets.h b/arch/avr32/include/asm/asm-offsets.h deleted file mode 100644 index d370ee36a182..000000000000 --- a/arch/avr32/include/asm/asm-offsets.h +++ /dev/null @@ -1 +0,0 @@ -#include <generated/asm-offsets.h> diff --git a/arch/avr32/include/asm/asm.h b/arch/avr32/include/asm/asm.h deleted file mode 100644 index a2c64f404b98..000000000000 --- a/arch/avr32/include/asm/asm.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_ASM_H__ -#define __ASM_AVR32_ASM_H__ - -#include <asm/sysreg.h> -#include <asm/asm-offsets.h> -#include <asm/thread_info.h> - -#define mask_interrupts ssrf SYSREG_GM_OFFSET -#define mask_exceptions ssrf SYSREG_EM_OFFSET -#define unmask_interrupts csrf SYSREG_GM_OFFSET -#define unmask_exceptions csrf SYSREG_EM_OFFSET - -#ifdef CONFIG_FRAME_POINTER - .macro save_fp - st.w --sp, r7 - .endm - .macro restore_fp - ld.w r7, sp++ - .endm - .macro zero_fp - mov r7, 0 - .endm -#else - .macro save_fp - .endm - .macro restore_fp - .endm - .macro zero_fp - .endm -#endif - .macro get_thread_info reg - mov \reg, sp - andl \reg, ~(THREAD_SIZE - 1) & 0xffff - .endm - - /* Save and restore registers */ - .macro save_min sr, tmp=lr - pushm lr - mfsr \tmp, \sr - zero_fp - st.w --sp, \tmp - .endm - - .macro restore_min sr, tmp=lr - ld.w \tmp, sp++ - mtsr \sr, \tmp - popm lr - .endm - - .macro save_half sr, tmp=lr - save_fp - pushm r8-r9,r10,r11,r12,lr - zero_fp - mfsr \tmp, \sr - st.w --sp, \tmp - .endm - - .macro restore_half sr, tmp=lr - ld.w \tmp, sp++ - mtsr \sr, \tmp - popm r8-r9,r10,r11,r12,lr - restore_fp - .endm - - .macro save_full_user sr, tmp=lr - stmts --sp, r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,sp,lr - st.w --sp, lr - zero_fp - mfsr \tmp, \sr - st.w --sp, \tmp - .endm - - .macro restore_full_user sr, tmp=lr - ld.w \tmp, sp++ - mtsr \sr, \tmp - ld.w lr, sp++ - ldmts sp++, r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,sp,lr - .endm - - /* uaccess macros */ - .macro branch_if_kernel scratch, label - get_thread_info \scratch - ld.w \scratch, \scratch[TI_flags] - bld \scratch, TIF_USERSPACE - brcc \label - .endm - - .macro ret_if_privileged scratch, addr, size, ret - sub \scratch, \size, 1 - add \scratch, \addr - retcs \ret - retmi \ret - .endm - -#endif /* __ASM_AVR32_ASM_H__ */ diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h deleted file mode 100644 index 3d5ce38a6f0b..000000000000 --- a/arch/avr32/include/asm/atomic.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Atomic operations that C can't guarantee us. Useful for - * resource counting etc. - * - * But use these as seldom as possible since they are slower than - * regular operations. - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_ATOMIC_H -#define __ASM_AVR32_ATOMIC_H - -#include <linux/types.h> -#include <asm/cmpxchg.h> - -#define ATOMIC_INIT(i) { (i) } - -#define atomic_read(v) READ_ONCE((v)->counter) -#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) - -#define ATOMIC_OP_RETURN(op, asm_op, asm_con) \ -static inline int __atomic_##op##_return(int i, atomic_t *v) \ -{ \ - int result; \ - \ - asm volatile( \ - "/* atomic_" #op "_return */\n" \ - "1: ssrf 5\n" \ - " ld.w %0, %2\n" \ - " " #asm_op " %0, %3\n" \ - " stcond %1, %0\n" \ - " brne 1b" \ - : "=&r" (result), "=o" (v->counter) \ - : "m" (v->counter), #asm_con (i) \ - : "cc"); \ - \ - return result; \ -} - -#define ATOMIC_FETCH_OP(op, asm_op, asm_con) \ -static inline int __atomic_fetch_##op(int i, atomic_t *v) \ -{ \ - int result, val; \ - \ - asm volatile( \ - "/* atomic_fetch_" #op " */\n" \ - "1: ssrf 5\n" \ - " ld.w %0, %3\n" \ - " mov %1, %0\n" \ - " " #asm_op " %1, %4\n" \ - " stcond %2, %1\n" \ - " brne 1b" \ - : "=&r" (result), "=&r" (val), "=o" (v->counter) \ - : "m" (v->counter), #asm_con (i) \ - : "cc"); \ - \ - return result; \ -} - -ATOMIC_OP_RETURN(sub, sub, rKs21) -ATOMIC_OP_RETURN(add, add, r) -ATOMIC_FETCH_OP (sub, sub, rKs21) -ATOMIC_FETCH_OP (add, add, r) - -#define ATOMIC_OPS(op, asm_op) \ -ATOMIC_OP_RETURN(op, asm_op, r) \ -static inline void atomic_##op(int i, atomic_t *v) \ -{ \ - (void)__atomic_##op##_return(i, v); \ -} \ -ATOMIC_FETCH_OP(op, asm_op, r) \ -static inline int atomic_fetch_##op(int i, atomic_t *v) \ -{ \ - return __atomic_fetch_##op(i, v); \ -} - -ATOMIC_OPS(and, and) -ATOMIC_OPS(or, or) -ATOMIC_OPS(xor, eor) - -#undef ATOMIC_OPS -#undef ATOMIC_FETCH_OP -#undef ATOMIC_OP_RETURN - -/* - * Probably found the reason why we want to use sub with the signed 21-bit - * limit, it uses one less register than the add instruction that can add up to - * 32-bit values. - * - * Both instructions are 32-bit, to use a 16-bit instruction the immediate is - * very small; 4 bit. - * - * sub 32-bit, type IV, takes a register and subtracts a 21-bit immediate. - * add 32-bit, type II, adds two register values together. - */ -#define IS_21BIT_CONST(i) \ - (__builtin_constant_p(i) && ((i) >= -1048575) && ((i) <= 1048576)) - -/* - * atomic_add_return - add integer to atomic variable - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v. Returns the resulting value. - */ -static inline int atomic_add_return(int i, atomic_t *v) -{ - if (IS_21BIT_CONST(i)) - return __atomic_sub_return(-i, v); - - return __atomic_add_return(i, v); -} - -static inline int atomic_fetch_add(int i, atomic_t *v) -{ - if (IS_21BIT_CONST(i)) - return __atomic_fetch_sub(-i, v); - - return __atomic_fetch_add(i, v); -} - -/* - * atomic_sub_return - subtract the atomic variable - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically subtracts @i from @v. Returns the resulting value. - */ -static inline int atomic_sub_return(int i, atomic_t *v) -{ - if (IS_21BIT_CONST(i)) - return __atomic_sub_return(i, v); - - return __atomic_add_return(-i, v); -} - -static inline int atomic_fetch_sub(int i, atomic_t *v) -{ - if (IS_21BIT_CONST(i)) - return __atomic_fetch_sub(i, v); - - return __atomic_fetch_add(-i, v); -} - -/* - * __atomic_add_unless - add unless the number is a given value - * @v: pointer of type atomic_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, so long as it was not @u. - * Returns the old value of @v. -*/ -static inline int __atomic_add_unless(atomic_t *v, int a, int u) -{ - int tmp, old = atomic_read(v); - - if (IS_21BIT_CONST(a)) { - asm volatile( - "/* __atomic_sub_unless */\n" - "1: ssrf 5\n" - " ld.w %0, %2\n" - " cp.w %0, %4\n" - " breq 1f\n" - " sub %0, %3\n" - " stcond %1, %0\n" - " brne 1b\n" - "1:" - : "=&r"(tmp), "=o"(v->counter) - : "m"(v->counter), "rKs21"(-a), "rKs21"(u) - : "cc", "memory"); - } else { - asm volatile( - "/* __atomic_add_unless */\n" - "1: ssrf 5\n" - " ld.w %0, %2\n" - " cp.w %0, %4\n" - " breq 1f\n" - " add %0, %3\n" - " stcond %1, %0\n" - " brne 1b\n" - "1:" - : "=&r"(tmp), "=o"(v->counter) - : "m"(v->counter), "r"(a), "ir"(u) - : "cc", "memory"); - } - - return old; -} - -#undef IS_21BIT_CONST - -/* - * atomic_sub_if_positive - conditionally subtract integer from atomic variable - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically test @v and subtract @i if @v is greater or equal than @i. - * The function returns the old value of @v minus @i. - */ -static inline int atomic_sub_if_positive(int i, atomic_t *v) -{ - int result; - - asm volatile( - "/* atomic_sub_if_positive */\n" - "1: ssrf 5\n" - " ld.w %0, %2\n" - " sub %0, %3\n" - " brlt 1f\n" - " stcond %1, %0\n" - " brne 1b\n" - "1:" - : "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "ir"(i) - : "cc", "memory"); - - return result; -} - -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) -#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) - -#define atomic_sub(i, v) (void)atomic_sub_return(i, v) -#define atomic_add(i, v) (void)atomic_add_return(i, v) -#define atomic_dec(v) atomic_sub(1, (v)) -#define atomic_inc(v) atomic_add(1, (v)) - -#define atomic_dec_return(v) atomic_sub_return(1, v) -#define atomic_inc_return(v) atomic_add_return(1, v) - -#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) -#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) -#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) -#define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0) - -#define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v) - -#endif /* __ASM_AVR32_ATOMIC_H */ diff --git a/arch/avr32/include/asm/barrier.h b/arch/avr32/include/asm/barrier.h deleted file mode 100644 index 715100790fd0..000000000000 --- a/arch/avr32/include/asm/barrier.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_BARRIER_H -#define __ASM_AVR32_BARRIER_H - -/* - * Weirdest thing ever.. no full barrier, but it has a write barrier! - */ -#define wmb() asm volatile("sync 0" : : : "memory") - -#ifdef CONFIG_SMP -# error "The AVR32 port does not support SMP" -#endif - -#include <asm-generic/barrier.h> - -#endif /* __ASM_AVR32_BARRIER_H */ diff --git a/arch/avr32/include/asm/bitops.h b/arch/avr32/include/asm/bitops.h deleted file mode 100644 index 910d5374ce59..000000000000 --- a/arch/avr32/include/asm/bitops.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_BITOPS_H -#define __ASM_AVR32_BITOPS_H - -#ifndef _LINUX_BITOPS_H -#error only <linux/bitops.h> can be included directly -#endif - -#include <asm/byteorder.h> -#include <asm/barrier.h> - -/* - * set_bit - Atomically set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * This function is atomic and may not be reordered. See __set_bit() - * if you do not require the atomic guarantees. - * - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. - */ -static inline void set_bit(int nr, volatile void * addr) -{ - unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; - unsigned long tmp; - - if (__builtin_constant_p(nr)) { - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %2\n" - " sbr %0, %3\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p) - : "m"(*p), "i"(nr) - : "cc"); - } else { - unsigned long mask = 1UL << (nr % BITS_PER_LONG); - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %2\n" - " or %0, %3\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p) - : "m"(*p), "r"(mask) - : "cc"); - } -} - -/* - * clear_bit - Clears a bit in memory - * @nr: Bit to clear - * @addr: Address to start counting from - * - * clear_bit() is atomic and may not be reordered. However, it does - * not contain a memory barrier, so if it is used for locking purposes, - * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic() - * in order to ensure changes are visible on other processors. - */ -static inline void clear_bit(int nr, volatile void * addr) -{ - unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; - unsigned long tmp; - - if (__builtin_constant_p(nr)) { - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %2\n" - " cbr %0, %3\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p) - : "m"(*p), "i"(nr) - : "cc"); - } else { - unsigned long mask = 1UL << (nr % BITS_PER_LONG); - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %2\n" - " andn %0, %3\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p) - : "m"(*p), "r"(mask) - : "cc"); - } -} - -/* - * change_bit - Toggle a bit in memory - * @nr: Bit to change - * @addr: Address to start counting from - * - * change_bit() is atomic and may not be reordered. - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. - */ -static inline void change_bit(int nr, volatile void * addr) -{ - unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; - unsigned long mask = 1UL << (nr % BITS_PER_LONG); - unsigned long tmp; - - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %2\n" - " eor %0, %3\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p) - : "m"(*p), "r"(mask) - : "cc"); -} - -/* - * test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static inline int test_and_set_bit(int nr, volatile void * addr) -{ - unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; - unsigned long mask = 1UL << (nr % BITS_PER_LONG); - unsigned long tmp, old; - - if (__builtin_constant_p(nr)) { - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %3\n" - " mov %2, %0\n" - " sbr %0, %4\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p), "=&r"(old) - : "m"(*p), "i"(nr) - : "memory", "cc"); - } else { - asm volatile( - "1: ssrf 5\n" - " ld.w %2, %3\n" - " or %0, %2, %4\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p), "=&r"(old) - : "m"(*p), "r"(mask) - : "memory", "cc"); - } - - return (old & mask) != 0; -} - -/* - * test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to clear - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static inline int test_and_clear_bit(int nr, volatile void * addr) -{ - unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; - unsigned long mask = 1UL << (nr % BITS_PER_LONG); - unsigned long tmp, old; - - if (__builtin_constant_p(nr)) { - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %3\n" - " mov %2, %0\n" - " cbr %0, %4\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p), "=&r"(old) - : "m"(*p), "i"(nr) - : "memory", "cc"); - } else { - asm volatile( - "1: ssrf 5\n" - " ld.w %0, %3\n" - " mov %2, %0\n" - " andn %0, %4\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p), "=&r"(old) - : "m"(*p), "r"(mask) - : "memory", "cc"); - } - - return (old & mask) != 0; -} - -/* - * test_and_change_bit - Change a bit and return its old value - * @nr: Bit to change - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static inline int test_and_change_bit(int nr, volatile void * addr) -{ - unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; - unsigned long mask = 1UL << (nr % BITS_PER_LONG); - unsigned long tmp, old; - - asm volatile( - "1: ssrf 5\n" - " ld.w %2, %3\n" - " eor %0, %2, %4\n" - " stcond %1, %0\n" - " brne 1b" - : "=&r"(tmp), "=o"(*p), "=&r"(old) - : "m"(*p), "r"(mask) - : "memory", "cc"); - - return (old & mask) != 0; -} - -#include <asm-generic/bitops/non-atomic.h> - -/* Find First bit Set */ -static inline unsigned long __ffs(unsigned long word) -{ - unsigned long result; - - asm("brev %1\n\t" - "clz %0,%1" - : "=r"(result), "=&r"(word) - : "1"(word)); - return result; -} - -/* Find First Zero */ -static inline unsigned long ffz(unsigned long word) -{ - return __ffs(~word); -} - -/* Find Last bit Set */ -static inline int fls(unsigned long word) -{ - unsigned long result; - - asm("clz %0,%1" : "=r"(result) : "r"(word)); - return 32 - result; -} - -static inline int __fls(unsigned long word) -{ - return fls(word) - 1; -} - -unsigned long find_first_zero_bit(const unsigned long *addr, - unsigned long size); -#define find_first_zero_bit find_first_zero_bit - -unsigned long find_next_zero_bit(const unsigned long *addr, - unsigned long size, - unsigned long offset); -#define find_next_zero_bit find_next_zero_bit - -unsigned long find_first_bit(const unsigned long *addr, - unsigned long size); -#define find_first_bit find_first_bit - -unsigned long find_next_bit(const unsigned long *addr, - unsigned long size, - unsigned long offset); -#define find_next_bit find_next_bit - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - * - * The difference is that bit numbering starts at 1, and if no bit is set, - * the function returns 0. - */ -static inline int ffs(unsigned long word) -{ - if(word == 0) - return 0; - return __ffs(word) + 1; -} - -#include <asm-generic/bitops/fls64.h> -#include <asm-generic/bitops/sched.h> -#include <asm-generic/bitops/hweight.h> -#include <asm-generic/bitops/lock.h> - -extern unsigned long find_next_zero_bit_le(const void *addr, - unsigned long size, unsigned long offset); -#define find_next_zero_bit_le find_next_zero_bit_le - -extern unsigned long find_next_bit_le(const void *addr, - unsigned long size, unsigned long offset); -#define find_next_bit_le find_next_bit_le - -#include <asm-generic/bitops/le.h> -#include <asm-generic/bitops/ext2-atomic.h> - -#endif /* __ASM_AVR32_BITOPS_H */ diff --git a/arch/avr32/include/asm/bug.h b/arch/avr32/include/asm/bug.h deleted file mode 100644 index 85a92d099adb..000000000000 --- a/arch/avr32/include/asm/bug.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2006 Atmel Corporation - * - * 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 __ASM_AVR32_BUG_H -#define __ASM_AVR32_BUG_H - -#ifdef CONFIG_BUG - -/* - * According to our Chief Architect, this compact opcode is very - * unlikely to ever be implemented. - */ -#define AVR32_BUG_OPCODE 0x5df0 - -#ifdef CONFIG_DEBUG_BUGVERBOSE - -#define _BUG_OR_WARN(flags) \ - asm volatile( \ - "1: .hword %0\n" \ - " .section __bug_table,\"a\",@progbits\n" \ - "2: .long 1b\n" \ - " .long %1\n" \ - " .short %2\n" \ - " .short %3\n" \ - " .org 2b + %4\n" \ - " .previous" \ - : \ - : "i"(AVR32_BUG_OPCODE), "i"(__FILE__), \ - "i"(__LINE__), "i"(flags), \ - "i"(sizeof(struct bug_entry))) - -#else - -#define _BUG_OR_WARN(flags) \ - asm volatile( \ - "1: .hword %0\n" \ - " .section __bug_table,\"a\",@progbits\n" \ - "2: .long 1b\n" \ - " .short %1\n" \ - " .org 2b + %2\n" \ - " .previous" \ - : \ - : "i"(AVR32_BUG_OPCODE), "i"(flags), \ - "i"(sizeof(struct bug_entry))) - -#endif /* CONFIG_DEBUG_BUGVERBOSE */ - -#define BUG() \ - do { \ - _BUG_OR_WARN(0); \ - unreachable(); \ - } while (0) - -#define WARN_ON(condition) \ - ({ \ - int __ret_warn_on = !!(condition); \ - if (unlikely(__ret_warn_on)) \ - _BUG_OR_WARN(BUGFLAG_WARNING); \ - unlikely(__ret_warn_on); \ - }) - -#define HAVE_ARCH_BUG -#define HAVE_ARCH_WARN_ON - -#endif /* CONFIG_BUG */ - -#include <asm-generic/bug.h> - -struct pt_regs; -void die(const char *str, struct pt_regs *regs, long err); -void _exception(long signr, struct pt_regs *regs, int code, - unsigned long addr); - -#endif /* __ASM_AVR32_BUG_H */ diff --git a/arch/avr32/include/asm/bugs.h b/arch/avr32/include/asm/bugs.h deleted file mode 100644 index 278661bbd1b0..000000000000 --- a/arch/avr32/include/asm/bugs.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ -#ifndef __ASM_AVR32_BUGS_H -#define __ASM_AVR32_BUGS_H - -static void __init check_bugs(void) -{ - boot_cpu_data.loops_per_jiffy = loops_per_jiffy; -} - -#endif /* __ASM_AVR32_BUGS_H */ diff --git a/arch/avr32/include/asm/cache.h b/arch/avr32/include/asm/cache.h deleted file mode 100644 index c3a58a189a91..000000000000 --- a/arch/avr32/include/asm/cache.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __ASM_AVR32_CACHE_H -#define __ASM_AVR32_CACHE_H - -#define L1_CACHE_SHIFT 5 -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) - -/* - * Memory returned by kmalloc() may be used for DMA, so we must make - * sure that all such allocations are cache aligned. Otherwise, - * unrelated code may cause parts of the buffer to be read into the - * cache before the transfer is done, causing old data to be seen by - * the CPU. - */ -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES - -#ifndef __ASSEMBLER__ -struct cache_info { - unsigned int ways; - unsigned int sets; - unsigned int linesz; -}; -#endif /* __ASSEMBLER */ - -/* Cache operation constants */ -#define ICACHE_FLUSH 0x00 -#define ICACHE_INVALIDATE 0x01 -#define ICACHE_LOCK 0x02 -#define ICACHE_UNLOCK 0x03 -#define ICACHE_PREFETCH 0x04 - -#define DCACHE_FLUSH 0x08 -#define DCACHE_LOCK 0x09 -#define DCACHE_UNLOCK 0x0a -#define DCACHE_INVALIDATE 0x0b -#define DCACHE_CLEAN 0x0c -#define DCACHE_CLEAN_INVAL 0x0d - -#endif /* __ASM_AVR32_CACHE_H */ diff --git a/arch/avr32/include/asm/cacheflush.h b/arch/avr32/include/asm/cacheflush.h deleted file mode 100644 index 96e53820bbbd..000000000000 --- a/arch/avr32/include/asm/cacheflush.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_CACHEFLUSH_H -#define __ASM_AVR32_CACHEFLUSH_H - -/* Keep includes the same across arches. */ -#include <linux/mm.h> - -#define CACHE_OP_ICACHE_INVALIDATE 0x01 -#define CACHE_OP_DCACHE_INVALIDATE 0x0b -#define CACHE_OP_DCACHE_CLEAN 0x0c -#define CACHE_OP_DCACHE_CLEAN_INVAL 0x0d - -/* - * Invalidate any cacheline containing virtual address vaddr without - * writing anything back to memory. - * - * Note that this function may corrupt unrelated data structures when - * applied on buffers that are not cacheline aligned in both ends. - */ -static inline void invalidate_dcache_line(void *vaddr) -{ - asm volatile("cache %0[0], %1" - : - : "r"(vaddr), "n"(CACHE_OP_DCACHE_INVALIDATE) - : "memory"); -} - -/* - * Make sure any cacheline containing virtual address vaddr is written - * to memory. - */ -static inline void clean_dcache_line(void *vaddr) -{ - asm volatile("cache %0[0], %1" - : - : "r"(vaddr), "n"(CACHE_OP_DCACHE_CLEAN) - : "memory"); -} - -/* - * Make sure any cacheline containing virtual address vaddr is written - * to memory and then invalidate it. - */ -static inline void flush_dcache_line(void *vaddr) -{ - asm volatile("cache %0[0], %1" - : - : "r"(vaddr), "n"(CACHE_OP_DCACHE_CLEAN_INVAL) - : "memory"); -} - -/* - * Invalidate any instruction cacheline containing virtual address - * vaddr. - */ -static inline void invalidate_icache_line(void *vaddr) -{ - asm volatile("cache %0[0], %1" - : - : "r"(vaddr), "n"(CACHE_OP_ICACHE_INVALIDATE) - : "memory"); -} - -/* - * Applies the above functions on all lines that are touched by the - * specified virtual address range. - */ -void invalidate_dcache_region(void *start, size_t len); -void clean_dcache_region(void *start, size_t len); -void flush_dcache_region(void *start, size_t len); -void invalidate_icache_region(void *start, size_t len); - -/* - * Make sure any pending writes are completed before continuing. - */ -#define flush_write_buffer() asm volatile("sync 0" : : : "memory") - -/* - * The following functions are called when a virtual mapping changes. - * We do not need to flush anything in this case. - */ -#define flush_cache_all() do { } while (0) -#define flush_cache_mm(mm) do { } while (0) -#define flush_cache_dup_mm(mm) do { } while (0) -#define flush_cache_range(vma, start, end) do { } while (0) -#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) -#define flush_cache_vmap(start, end) do { } while (0) -#define flush_cache_vunmap(start, end) do { } while (0) - -/* - * I think we need to implement this one to be able to reliably - * execute pages from RAMDISK. However, if we implement the - * flush_dcache_*() functions, it might not be needed anymore. - * - * #define flush_icache_page(vma, page) do { } while (0) - */ -extern void flush_icache_page(struct vm_area_struct *vma, struct page *page); - -/* - * These are (I think) related to D-cache aliasing. We might need to - * do something here, but only for certain configurations. No such - * configurations exist at this time. - */ -#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 -#define flush_dcache_page(page) do { } while (0) -#define flush_dcache_mmap_lock(page) do { } while (0) -#define flush_dcache_mmap_unlock(page) do { } while (0) - -/* - * These are for I/D cache coherency. In this case, we do need to - * flush with all configurations. - */ -extern void flush_icache_range(unsigned long start, unsigned long end); - -extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, - unsigned long vaddr, void *dst, const void *src, - unsigned long len); - -static inline void copy_from_user_page(struct vm_area_struct *vma, - struct page *page, unsigned long vaddr, void *dst, - const void *src, unsigned long len) -{ - memcpy(dst, src, len); -} - -#endif /* __ASM_AVR32_CACHEFLUSH_H */ diff --git a/arch/avr32/include/asm/checksum.h b/arch/avr32/include/asm/checksum.h deleted file mode 100644 index 4ab7d5bdaf53..000000000000 --- a/arch/avr32/include/asm/checksum.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_CHECKSUM_H -#define __ASM_AVR32_CHECKSUM_H - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -__wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * the same as csum_partial, but copies from src while it - * checksums, and handles user-space pointer exceptions correctly, when needed. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ -__wsum csum_partial_copy_generic(const void *src, void *dst, int len, - __wsum sum, int *src_err_ptr, - int *dst_err_ptr); - -/* - * Note: when you get a NULL pointer exception here this means someone - * passed in an incorrect kernel address to one of these functions. - * - * If you use these functions directly please don't forget the - * access_ok(). - */ -static inline -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) -{ - return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); -} - -static inline -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *err_ptr) -{ - return csum_partial_copy_generic((const void __force *)src, dst, len, - sum, err_ptr, NULL); -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - unsigned int sum, tmp; - - __asm__ __volatile__( - " ld.w %0, %1++\n" - " ld.w %3, %1++\n" - " sub %2, 4\n" - " add %0, %3\n" - " ld.w %3, %1++\n" - " adc %0, %0, %3\n" - " ld.w %3, %1++\n" - " adc %0, %0, %3\n" - " acr %0\n" - "1: ld.w %3, %1++\n" - " add %0, %3\n" - " acr %0\n" - " sub %2, 1\n" - " brne 1b\n" - " lsl %3, %0, 16\n" - " andl %0, 0\n" - " mov %2, 0xffff\n" - " add %0, %3\n" - " adc %0, %0, %2\n" - " com %0\n" - " lsr %0, 16\n" - : "=r"(sum), "=r"(iph), "=r"(ihl), "=r"(tmp) - : "1"(iph), "2"(ihl) - : "memory", "cc"); - return (__force __sum16)sum; -} - -/* - * Fold a partial checksum - */ - -static inline __sum16 csum_fold(__wsum sum) -{ - unsigned int tmp; - - asm(" bfextu %1, %0, 0, 16\n" - " lsr %0, 16\n" - " add %0, %1\n" - " bfextu %1, %0, 16, 16\n" - " add %0, %1" - : "=&r"(sum), "=&r"(tmp) - : "0"(sum)); - - return (__force __sum16)~sum; -} - -static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, - __u32 len, __u8 proto, - __wsum sum) -{ - asm(" add %0, %1\n" - " adc %0, %0, %2\n" - " adc %0, %0, %3\n" - " acr %0" - : "=r"(sum) - : "r"(daddr), "r"(saddr), "r"(len + proto), - "0"(sum) - : "cc"); - - return sum; -} - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - __u32 len, __u8 proto, - __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ - -static inline __sum16 ip_compute_csum(const void *buff, int len) -{ - return csum_fold(csum_partial(buff, len, 0)); -} - -#endif /* __ASM_AVR32_CHECKSUM_H */ diff --git a/arch/avr32/include/asm/cmpxchg.h b/arch/avr32/include/asm/cmpxchg.h deleted file mode 100644 index 572739b4c4b4..000000000000 --- a/arch/avr32/include/asm/cmpxchg.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Atomic operations that C can't guarantee us. Useful for - * resource counting etc. - * - * But use these as seldom as possible since they are slower than - * regular operations. - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_CMPXCHG_H -#define __ASM_AVR32_CMPXCHG_H - -#define xchg(ptr,x) \ - ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - -extern void __xchg_called_with_bad_pointer(void); - -static inline unsigned long xchg_u32(u32 val, volatile u32 *m) -{ - u32 ret; - - asm volatile("xchg %[ret], %[m], %[val]" - : [ret] "=&r"(ret), "=m"(*m) - : "m"(*m), [m] "r"(m), [val] "r"(val) - : "memory"); - return ret; -} - -static inline unsigned long __xchg(unsigned long x, - volatile void *ptr, - int size) -{ - switch(size) { - case 4: - return xchg_u32(x, ptr); - default: - __xchg_called_with_bad_pointer(); - return x; - } -} - -static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, - unsigned long new) -{ - __u32 ret; - - asm volatile( - "1: ssrf 5\n" - " ld.w %[ret], %[m]\n" - " cp.w %[ret], %[old]\n" - " brne 2f\n" - " stcond %[m], %[new]\n" - " brne 1b\n" - "2:\n" - : [ret] "=&r"(ret), [m] "=m"(*m) - : "m"(m), [old] "Ks21r"(old), [new] "r"(new) - : "memory", "cc"); - return ret; -} - -extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( - volatile int * m, unsigned long old, unsigned long new); -#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels - -/* This function doesn't exist, so you'll get a linker error - if something tries to do an invalid cmpxchg(). */ -extern void __cmpxchg_called_with_bad_pointer(void); - -static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 4: - return __cmpxchg_u32(ptr, old, new); - case 8: - return __cmpxchg_u64(ptr, old, new); - } - - __cmpxchg_called_with_bad_pointer(); - return old; -} - -#define cmpxchg(ptr, old, new) \ - ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \ - (unsigned long)(new), \ - sizeof(*(ptr)))) - -#include <asm-generic/cmpxchg-local.h> - -static inline unsigned long __cmpxchg_local(volatile void *ptr, - unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 4: - return __cmpxchg_u32(ptr, old, new); - default: - return __cmpxchg_local_generic(ptr, old, new, size); - } - - return old; -} - -#define cmpxchg_local(ptr, old, new) \ - ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old), \ - (unsigned long)(new), \ - sizeof(*(ptr)))) - -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) - -#endif /* __ASM_AVR32_CMPXCHG_H */ diff --git a/arch/avr32/include/asm/current.h b/arch/avr32/include/asm/current.h deleted file mode 100644 index c7b0549eab8a..000000000000 --- a/arch/avr32/include/asm/current.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __ASM_AVR32_CURRENT_H -#define __ASM_AVR32_CURRENT_H - -#include <linux/thread_info.h> - -struct task_struct; - -inline static struct task_struct * get_current(void) -{ - return current_thread_info()->task; -} - -#define current get_current() - -#endif /* __ASM_AVR32_CURRENT_H */ diff --git a/arch/avr32/include/asm/dma-mapping.h b/arch/avr32/include/asm/dma-mapping.h deleted file mode 100644 index 7388451f9905..000000000000 --- a/arch/avr32/include/asm/dma-mapping.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __ASM_AVR32_DMA_MAPPING_H -#define __ASM_AVR32_DMA_MAPPING_H - -extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - int direction); - -extern const struct dma_map_ops avr32_dma_ops; - -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) -{ - return &avr32_dma_ops; -} - -#endif /* __ASM_AVR32_DMA_MAPPING_H */ diff --git a/arch/avr32/include/asm/dma.h b/arch/avr32/include/asm/dma.h deleted file mode 100644 index 9e91205590ac..000000000000 --- a/arch/avr32/include/asm/dma.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_AVR32_DMA_H -#define __ASM_AVR32_DMA_H - -/* The maximum address that we can perform a DMA transfer to on this platform. - * Not really applicable to AVR32, but some functions need it. */ -#define MAX_DMA_ADDRESS 0xffffffff - -#endif /* __ASM_AVR32_DMA_H */ diff --git a/arch/avr32/include/asm/elf.h b/arch/avr32/include/asm/elf.h deleted file mode 100644 index 0388ece75b02..000000000000 --- a/arch/avr32/include/asm/elf.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef __ASM_AVR32_ELF_H -#define __ASM_AVR32_ELF_H - -/* AVR32 relocation numbers */ -#define R_AVR32_NONE 0 -#define R_AVR32_32 1 -#define R_AVR32_16 2 -#define R_AVR32_8 3 -#define R_AVR32_32_PCREL 4 -#define R_AVR32_16_PCREL 5 -#define R_AVR32_8_PCREL 6 -#define R_AVR32_DIFF32 7 -#define R_AVR32_DIFF16 8 -#define R_AVR32_DIFF8 9 -#define R_AVR32_GOT32 10 -#define R_AVR32_GOT16 11 -#define R_AVR32_GOT8 12 -#define R_AVR32_21S 13 -#define R_AVR32_16U 14 -#define R_AVR32_16S 15 -#define R_AVR32_8S 16 -#define R_AVR32_8S_EXT 17 -#define R_AVR32_22H_PCREL 18 -#define R_AVR32_18W_PCREL 19 -#define R_AVR32_16B_PCREL 20 -#define R_AVR32_16N_PCREL 21 -#define R_AVR32_14UW_PCREL 22 -#define R_AVR32_11H_PCREL 23 -#define R_AVR32_10UW_PCREL 24 -#define R_AVR32_9H_PCREL 25 -#define R_AVR32_9UW_PCREL 26 -#define R_AVR32_HI16 27 -#define R_AVR32_LO16 28 -#define R_AVR32_GOTPC 29 -#define R_AVR32_GOTCALL 30 -#define R_AVR32_LDA_GOT 31 -#define R_AVR32_GOT21S 32 -#define R_AVR32_GOT18SW 33 -#define R_AVR32_GOT16S 34 -#define R_AVR32_GOT7UW 35 -#define R_AVR32_32_CPENT 36 -#define R_AVR32_CPCALL 37 -#define R_AVR32_16_CP 38 -#define R_AVR32_9W_CP 39 -#define R_AVR32_RELATIVE 40 -#define R_AVR32_GLOB_DAT 41 -#define R_AVR32_JMP_SLOT 42 -#define R_AVR32_ALIGN 43 - -/* - * ELF register definitions.. - */ - -#include <asm/ptrace.h> -#include <asm/user.h> - -typedef unsigned long elf_greg_t; - -#define ELF_NGREG (sizeof (struct pt_regs) / sizeof (elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_fpu_struct elf_fpregset_t; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ( (x)->e_machine == EM_AVR32 ) - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#ifdef __LITTLE_ENDIAN__ -#define ELF_DATA ELFDATA2LSB -#else -#define ELF_DATA ELFDATA2MSB -#endif -#define ELF_ARCH EM_AVR32 - -#define ELF_EXEC_PAGESIZE 4096 - -/* This is the location that an ET_DYN program is loaded if exec'ed. Typical - use of this is to invoke "./ld.so someprog" to test out a new version of - the loader. We need to make sure that it is out of the way of the program - that it will "exec", and that there is sufficient room for the brk. */ - -#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) - - -/* This yields a mask that user programs can use to figure out what - instruction set this CPU supports. This could be done in user space, - but it's not easy, and we've already done it here. */ - -#define ELF_HWCAP (0) - -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. - - For the moment, we have only optimizations for the Intel generations, - but that could change... */ - -#define ELF_PLATFORM (NULL) - -#endif /* __ASM_AVR32_ELF_H */ diff --git a/arch/avr32/include/asm/fb.h b/arch/avr32/include/asm/fb.h deleted file mode 100644 index 41baf84ad402..000000000000 --- a/arch/avr32/include/asm/fb.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _ASM_FB_H_ -#define _ASM_FB_H_ - -#include <linux/fb.h> -#include <linux/fs.h> -#include <asm/page.h> - -static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, - unsigned long off) -{ - vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot) - & ~_PAGE_CACHABLE) - | (_PAGE_BUFFER | _PAGE_DIRTY)); -} - -static inline int fb_is_primary_device(struct fb_info *info) -{ - return 0; -} - -#endif /* _ASM_FB_H_ */ diff --git a/arch/avr32/include/asm/ftrace.h b/arch/avr32/include/asm/ftrace.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/avr32/include/asm/ftrace.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/avr32/include/asm/gpio.h b/arch/avr32/include/asm/gpio.h deleted file mode 100644 index b771f7105964..000000000000 --- a/arch/avr32/include/asm/gpio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_AVR32_GPIO_H -#define __ASM_AVR32_GPIO_H - -#include <mach/gpio.h> - -#endif /* __ASM_AVR32_GPIO_H */ diff --git a/arch/avr32/include/asm/hardirq.h b/arch/avr32/include/asm/hardirq.h deleted file mode 100644 index 9e36e3ff77d2..000000000000 --- a/arch/avr32/include/asm/hardirq.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_AVR32_HARDIRQ_H -#define __ASM_AVR32_HARDIRQ_H -#ifndef __ASSEMBLY__ -#include <asm-generic/hardirq.h> -#endif /* __ASSEMBLY__ */ -#endif /* __ASM_AVR32_HARDIRQ_H */ diff --git a/arch/avr32/include/asm/hw_irq.h b/arch/avr32/include/asm/hw_irq.h deleted file mode 100644 index a36f9fcb8fcd..000000000000 --- a/arch/avr32/include/asm/hw_irq.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_AVR32_HW_IRQ_H -#define __ASM_AVR32_HW_IRQ_H - -static inline void hw_resend_irq(struct irq_chip *h, unsigned int i) -{ - /* Nothing to do */ -} - -#endif /* __ASM_AVR32_HW_IRQ_H */ diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h deleted file mode 100644 index f855646e0db7..000000000000 --- a/arch/avr32/include/asm/io.h +++ /dev/null @@ -1,329 +0,0 @@ -#ifndef __ASM_AVR32_IO_H -#define __ASM_AVR32_IO_H - -#include <linux/bug.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/types.h> - -#include <asm/addrspace.h> -#include <asm/byteorder.h> - -#include <mach/io.h> - -/* virt_to_phys will only work when address is in P1 or P2 */ -static __inline__ unsigned long virt_to_phys(volatile void *address) -{ - return PHYSADDR(address); -} - -static __inline__ void * phys_to_virt(unsigned long address) -{ - return (void *)P1SEGADDR(address); -} - -#define cached_to_phys(addr) ((unsigned long)PHYSADDR(addr)) -#define uncached_to_phys(addr) ((unsigned long)PHYSADDR(addr)) -#define phys_to_cached(addr) ((void *)P1SEGADDR(addr)) -#define phys_to_uncached(addr) ((void *)P2SEGADDR(addr)) - -/* - * Generic IO read/write. These perform native-endian accesses. Note - * that some architectures will want to re-define __raw_{read,write}w. - */ -extern void __raw_writesb(void __iomem *addr, const void *data, int bytelen); -extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen); -extern void __raw_writesl(void __iomem *addr, const void *data, int longlen); - -extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen); -extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen); -extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); - -static inline void __raw_writeb(u8 v, volatile void __iomem *addr) -{ - *(volatile u8 __force *)addr = v; -} -static inline void __raw_writew(u16 v, volatile void __iomem *addr) -{ - *(volatile u16 __force *)addr = v; -} -static inline void __raw_writel(u32 v, volatile void __iomem *addr) -{ - *(volatile u32 __force *)addr = v; -} - -static inline u8 __raw_readb(const volatile void __iomem *addr) -{ - return *(const volatile u8 __force *)addr; -} -static inline u16 __raw_readw(const volatile void __iomem *addr) -{ - return *(const volatile u16 __force *)addr; -} -static inline u32 __raw_readl(const volatile void __iomem *addr) -{ - return *(const volatile u32 __force *)addr; -} - -/* Convert I/O port address to virtual address */ -#ifndef __io -# define __io(p) ((void *)phys_to_uncached(p)) -#endif - -/* - * Not really sure about the best way to slow down I/O on - * AVR32. Defining it as a no-op until we have an actual test case. - */ -#define SLOW_DOWN_IO do { } while (0) - -#define __BUILD_MEMORY_SINGLE(pfx, bwl, type) \ -static inline void \ -pfx##write##bwl(type val, volatile void __iomem *addr) \ -{ \ - volatile type *__addr; \ - type __val; \ - \ - __addr = (void *)__swizzle_addr_##bwl((unsigned long)(addr)); \ - __val = pfx##ioswab##bwl(__addr, val); \ - \ - BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ - \ - *__addr = __val; \ -} \ - \ -static inline type pfx##read##bwl(const volatile void __iomem *addr) \ -{ \ - volatile type *__addr; \ - type __val; \ - \ - __addr = (void *)__swizzle_addr_##bwl((unsigned long)(addr)); \ - \ - BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ - \ - __val = *__addr; \ - return pfx##ioswab##bwl(__addr, __val); \ -} - -#define __BUILD_IOPORT_SINGLE(pfx, bwl, type, p, slow) \ -static inline void pfx##out##bwl##p(type val, unsigned long port) \ -{ \ - volatile type *__addr; \ - type __val; \ - \ - __addr = __io(__swizzle_addr_##bwl(port)); \ - __val = pfx##ioswab##bwl(__addr, val); \ - \ - BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ - \ - *__addr = __val; \ - slow; \ -} \ - \ -static inline type pfx##in##bwl##p(unsigned long port) \ -{ \ - volatile type *__addr; \ - type __val; \ - \ - __addr = __io(__swizzle_addr_##bwl(port)); \ - \ - BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ - \ - __val = *__addr; \ - slow; \ - \ - return pfx##ioswab##bwl(__addr, __val); \ -} - -#define __BUILD_MEMORY_PFX(bus, bwl, type) \ - __BUILD_MEMORY_SINGLE(bus, bwl, type) - -#define BUILDIO_MEM(bwl, type) \ - __BUILD_MEMORY_PFX(, bwl, type) \ - __BUILD_MEMORY_PFX(__mem_, bwl, type) - -#define __BUILD_IOPORT_PFX(bus, bwl, type) \ - __BUILD_IOPORT_SINGLE(bus, bwl, type, ,) \ - __BUILD_IOPORT_SINGLE(bus, bwl, type, _p, SLOW_DOWN_IO) - -#define BUILDIO_IOPORT(bwl, type) \ - __BUILD_IOPORT_PFX(, bwl, type) \ - __BUILD_IOPORT_PFX(__mem_, bwl, type) - -BUILDIO_MEM(b, u8) -BUILDIO_MEM(w, u16) -BUILDIO_MEM(l, u32) - -BUILDIO_IOPORT(b, u8) -BUILDIO_IOPORT(w, u16) -BUILDIO_IOPORT(l, u32) - -#define readb_relaxed readb -#define readw_relaxed readw -#define readl_relaxed readl - -#define readb_be __raw_readb -#define readw_be __raw_readw -#define readl_be __raw_readl - -#define writeb_relaxed writeb -#define writew_relaxed writew -#define writel_relaxed writel - -#define writeb_be __raw_writeb -#define writew_be __raw_writew -#define writel_be __raw_writel - -#define __BUILD_MEMORY_STRING(bwl, type) \ -static inline void writes##bwl(volatile void __iomem *addr, \ - const void *data, unsigned int count) \ -{ \ - const type *__data = data; \ - \ - while (count--) \ - __mem_write##bwl(*__data++, addr); \ -} \ - \ -static inline void reads##bwl(const volatile void __iomem *addr, \ - void *data, unsigned int count) \ -{ \ - type *__data = data; \ - \ - while (count--) \ - *__data++ = __mem_read##bwl(addr); \ -} - -#define __BUILD_IOPORT_STRING(bwl, type) \ -static inline void outs##bwl(unsigned long port, const void *data, \ - unsigned int count) \ -{ \ - const type *__data = data; \ - \ - while (count--) \ - __mem_out##bwl(*__data++, port); \ -} \ - \ -static inline void ins##bwl(unsigned long port, void *data, \ - unsigned int count) \ -{ \ - type *__data = data; \ - \ - while (count--) \ - *__data++ = __mem_in##bwl(port); \ -} - -#define BUILDSTRING(bwl, type) \ - __BUILD_MEMORY_STRING(bwl, type) \ - __BUILD_IOPORT_STRING(bwl, type) - -BUILDSTRING(b, u8) -BUILDSTRING(w, u16) -BUILDSTRING(l, u32) - -/* - * io{read,write}{8,16,32} macros in both le (for PCI style consumers) and native be - */ -#ifndef ioread8 - -#define ioread8(p) ((unsigned int)readb(p)) - -#define ioread16(p) ((unsigned int)readw(p)) -#define ioread16be(p) ((unsigned int)__raw_readw(p)) - -#define ioread32(p) ((unsigned int)readl(p)) -#define ioread32be(p) ((unsigned int)__raw_readl(p)) - -#define iowrite8(v,p) writeb(v, p) - -#define iowrite16(v,p) writew(v, p) -#define iowrite16be(v,p) __raw_writew(v, p) - -#define iowrite32(v,p) writel(v, p) -#define iowrite32be(v,p) __raw_writel(v, p) - -#define ioread8_rep(p,d,c) readsb(p,d,c) -#define ioread16_rep(p,d,c) readsw(p,d,c) -#define ioread32_rep(p,d,c) readsl(p,d,c) - -#define iowrite8_rep(p,s,c) writesb(p,s,c) -#define iowrite16_rep(p,s,c) writesw(p,s,c) -#define iowrite32_rep(p,s,c) writesl(p,s,c) - -#endif - -static inline void memcpy_fromio(void * to, const volatile void __iomem *from, - unsigned long count) -{ - memcpy(to, (const void __force *)from, count); -} - -static inline void memcpy_toio(volatile void __iomem *to, const void * from, - unsigned long count) -{ - memcpy((void __force *)to, from, count); -} - -static inline void memset_io(volatile void __iomem *addr, unsigned char val, - unsigned long count) -{ - memset((void __force *)addr, val, count); -} - -#define mmiowb() - -#define IO_SPACE_LIMIT 0xffffffff - -extern void __iomem *__ioremap(unsigned long offset, size_t size, - unsigned long flags); -extern void __iounmap(void __iomem *addr); - -/* - * ioremap - map bus memory into CPU space - * @offset bus address of the memory - * @size size of the resource to map - * - * ioremap performs a platform specific sequence of operations to make - * bus memory CPU accessible via the readb/.../writel functions and - * the other mmio helpers. The returned address is not guaranteed to - * be usable directly as a virtual address. - */ -#define ioremap(offset, size) \ - __ioremap((offset), (size), 0) - -#define ioremap_nocache(offset, size) \ - __ioremap((offset), (size), 0) - -#define iounmap(addr) \ - __iounmap(addr) - -#define ioremap_wc ioremap_nocache -#define ioremap_wt ioremap_nocache -#define ioremap_uc ioremap_nocache - -#define cached(addr) P1SEGADDR(addr) -#define uncached(addr) P2SEGADDR(addr) - -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#define page_to_bus page_to_phys -#define bus_to_page phys_to_page - -/* - * Create a virtual mapping cookie for an IO port range. There exists - * no such thing as port-based I/O on AVR32, so a regular ioremap() - * should do what we need. - */ -#define ioport_map(port, nr) ioremap(port, nr) -#define ioport_unmap(port) iounmap(port) - -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - -#endif /* __ASM_AVR32_IO_H */ diff --git a/arch/avr32/include/asm/irq.h b/arch/avr32/include/asm/irq.h deleted file mode 100644 index 6fa8913f8548..000000000000 --- a/arch/avr32/include/asm/irq.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __ASM_AVR32_IRQ_H -#define __ASM_AVR32_IRQ_H - -#define NR_INTERNAL_IRQS 64 - -#include <mach/irq.h> - -#ifndef NR_IRQS -#define NR_IRQS (NR_INTERNAL_IRQS) -#endif - -#define irq_canonicalize(i) (i) - -#ifndef __ASSEMBLER__ -int nmi_enable(void); -void nmi_disable(void); - -/* - * Returns a bitmask of pending interrupts in a group. - */ -extern unsigned long intc_get_pending(unsigned int group); -#endif - -#endif /* __ASM_AVR32_IOCTLS_H */ diff --git a/arch/avr32/include/asm/irqflags.h b/arch/avr32/include/asm/irqflags.h deleted file mode 100644 index 006e9487372d..000000000000 --- a/arch/avr32/include/asm/irqflags.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_IRQFLAGS_H -#define __ASM_AVR32_IRQFLAGS_H - -#include <linux/types.h> -#include <asm/sysreg.h> - -static inline unsigned long arch_local_save_flags(void) -{ - return sysreg_read(SR); -} - -/* - * This will restore ALL status register flags, not only the interrupt - * mask flag. - * - * The empty asm statement informs the compiler of this fact while - * also serving as a barrier. - */ -static inline void arch_local_irq_restore(unsigned long flags) -{ - sysreg_write(SR, flags); - asm volatile("" : : : "memory", "cc"); -} - -static inline void arch_local_irq_disable(void) -{ - asm volatile("ssrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory"); -} - -static inline void arch_local_irq_enable(void) -{ - asm volatile("csrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory"); -} - -static inline bool arch_irqs_disabled_flags(unsigned long flags) -{ - return (flags & SYSREG_BIT(GM)) != 0; -} - -static inline bool arch_irqs_disabled(void) -{ - return arch_irqs_disabled_flags(arch_local_save_flags()); -} - -static inline unsigned long arch_local_irq_save(void) -{ - unsigned long flags = arch_local_save_flags(); - - arch_local_irq_disable(); - - return flags; -} - -#endif /* __ASM_AVR32_IRQFLAGS_H */ diff --git a/arch/avr32/include/asm/kdebug.h b/arch/avr32/include/asm/kdebug.h deleted file mode 100644 index f930ce286803..000000000000 --- a/arch/avr32/include/asm/kdebug.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ASM_AVR32_KDEBUG_H -#define __ASM_AVR32_KDEBUG_H - -/* Grossly misnamed. */ -enum die_val { - DIE_BREAKPOINT, - DIE_SSTEP, - DIE_NMI, - DIE_OOPS, -}; - -#endif /* __ASM_AVR32_KDEBUG_H */ diff --git a/arch/avr32/include/asm/kmap_types.h b/arch/avr32/include/asm/kmap_types.h deleted file mode 100644 index 479330b89796..000000000000 --- a/arch/avr32/include/asm/kmap_types.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ASM_AVR32_KMAP_TYPES_H -#define __ASM_AVR32_KMAP_TYPES_H - -#ifdef CONFIG_DEBUG_HIGHMEM -# define KM_TYPE_NR 29 -#else -# define KM_TYPE_NR 14 -#endif - -#endif /* __ASM_AVR32_KMAP_TYPES_H */ diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h deleted file mode 100644 index 28dfc61ad384..000000000000 --- a/arch/avr32/include/asm/kprobes.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Kernel Probes (KProbes) - * - * Copyright (C) 2005-2006 Atmel Corporation - * Copyright (C) IBM Corporation, 2002, 2004 - * - * 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 __ASM_AVR32_KPROBES_H -#define __ASM_AVR32_KPROBES_H - -#include <asm-generic/kprobes.h> - -#define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */ - -#ifdef CONFIG_KPROBES -#include <linux/types.h> - -typedef u16 kprobe_opcode_t; -#define MAX_INSN_SIZE 2 -#define MAX_STACK_SIZE 64 /* 32 would probably be OK */ - -#define kretprobe_blacklist_size 0 - -#define arch_remove_kprobe(p) do { } while (0) - -/* Architecture specific copy of original instruction */ -struct arch_specific_insn { - kprobe_opcode_t insn[MAX_INSN_SIZE]; -}; - -struct prev_kprobe { - struct kprobe *kp; - unsigned int status; -}; - -/* per-cpu kprobe control block */ -struct kprobe_ctlblk { - unsigned int kprobe_status; - struct prev_kprobe prev_kprobe; - struct pt_regs jprobe_saved_regs; - char jprobes_stack[MAX_STACK_SIZE]; -}; - -extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); -extern int kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data); - -#define flush_insn_slot(p) do { } while (0) - -#endif /* CONFIG_KPROBES */ -#endif /* __ASM_AVR32_KPROBES_H */ diff --git a/arch/avr32/include/asm/linkage.h b/arch/avr32/include/asm/linkage.h deleted file mode 100644 index f7b285e910d4..000000000000 --- a/arch/avr32/include/asm/linkage.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_LINKAGE_H -#define __ASM_LINKAGE_H - -#define __ALIGN .balign 2 -#define __ALIGN_STR ".balign 2" - -#endif /* __ASM_LINKAGE_H */ diff --git a/arch/avr32/include/asm/mmu.h b/arch/avr32/include/asm/mmu.h deleted file mode 100644 index 60c2d2650d32..000000000000 --- a/arch/avr32/include/asm/mmu.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ASM_AVR32_MMU_H -#define __ASM_AVR32_MMU_H - -/* Default "unsigned long" context */ -typedef unsigned long mm_context_t; - -#define MMU_ITLB_ENTRIES 64 -#define MMU_DTLB_ENTRIES 64 - -#endif /* __ASM_AVR32_MMU_H */ diff --git a/arch/avr32/include/asm/mmu_context.h b/arch/avr32/include/asm/mmu_context.h deleted file mode 100644 index cd87abba8db7..000000000000 --- a/arch/avr32/include/asm/mmu_context.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * ASID handling taken from SH implementation. - * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2003 Paul Mundt - * - * 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 __ASM_AVR32_MMU_CONTEXT_H -#define __ASM_AVR32_MMU_CONTEXT_H - -#include <linux/mm_types.h> - -#include <asm/tlbflush.h> -#include <asm/sysreg.h> -#include <asm-generic/mm_hooks.h> - -/* - * The MMU "context" consists of two things: - * (a) TLB cache version - * (b) ASID (Address Space IDentifier) - */ -#define MMU_CONTEXT_ASID_MASK 0x000000ff -#define MMU_CONTEXT_VERSION_MASK 0xffffff00 -#define MMU_CONTEXT_FIRST_VERSION 0x00000100 -#define NO_CONTEXT 0 - -#define MMU_NO_ASID 0x100 - -/* Virtual Page Number mask */ -#define MMU_VPN_MASK 0xfffff000 - -/* Cache of MMU context last used */ -extern unsigned long mmu_context_cache; - -/* - * Get MMU context if needed - */ -static inline void -get_mmu_context(struct mm_struct *mm) -{ - unsigned long mc = mmu_context_cache; - - if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0) - /* It's up to date, do nothing */ - return; - - /* It's old, we need to get new context with new version */ - mc = ++mmu_context_cache; - if (!(mc & MMU_CONTEXT_ASID_MASK)) { - /* - * We have exhausted all ASIDs of this version. - * Flush the TLB and start new cycle. - */ - flush_tlb_all(); - /* - * Fix version. Note that we avoid version #0 - * to distinguish NO_CONTEXT. - */ - if (!mc) - mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION; - } - mm->context = mc; -} - -/* - * Initialize the context related info for a new mm_struct - * instance. - */ -static inline int init_new_context(struct task_struct *tsk, - struct mm_struct *mm) -{ - mm->context = NO_CONTEXT; - return 0; -} - -/* - * Destroy context related info for an mm_struct that is about - * to be put to rest. - */ -static inline void destroy_context(struct mm_struct *mm) -{ - /* Do nothing */ -} - -static inline void set_asid(unsigned long asid) -{ - /* XXX: We're destroying TLBEHI[8:31] */ - sysreg_write(TLBEHI, asid & MMU_CONTEXT_ASID_MASK); - cpu_sync_pipeline(); -} - -static inline unsigned long get_asid(void) -{ - unsigned long asid; - - asid = sysreg_read(TLBEHI); - return asid & MMU_CONTEXT_ASID_MASK; -} - -static inline void activate_context(struct mm_struct *mm) -{ - get_mmu_context(mm); - set_asid(mm->context & MMU_CONTEXT_ASID_MASK); -} - -static inline void switch_mm(struct mm_struct *prev, - struct mm_struct *next, - struct task_struct *tsk) -{ - if (likely(prev != next)) { - unsigned long __pgdir = (unsigned long)next->pgd; - - sysreg_write(PTBR, __pgdir); - activate_context(next); - } -} - -#define deactivate_mm(tsk,mm) do { } while(0) - -#define activate_mm(prev, next) switch_mm((prev), (next), NULL) - -static inline void -enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - - -static inline void enable_mmu(void) -{ - sysreg_write(MMUCR, (SYSREG_BIT(MMUCR_S) - | SYSREG_BIT(E) - | SYSREG_BIT(MMUCR_I))); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - - if (mmu_context_cache == NO_CONTEXT) - mmu_context_cache = MMU_CONTEXT_FIRST_VERSION; - - set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK); -} - -static inline void disable_mmu(void) -{ - sysreg_write(MMUCR, SYSREG_BIT(MMUCR_S)); -} - -#endif /* __ASM_AVR32_MMU_CONTEXT_H */ diff --git a/arch/avr32/include/asm/module.h b/arch/avr32/include/asm/module.h deleted file mode 100644 index 3f083d385a64..000000000000 --- a/arch/avr32/include/asm/module.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ASM_AVR32_MODULE_H -#define __ASM_AVR32_MODULE_H - -#include <asm-generic/module.h> - -struct mod_arch_syminfo { - unsigned long got_offset; - int got_initialized; -}; - -struct mod_arch_specific { - /* Starting offset of got in the module core memory. */ - unsigned long got_offset; - /* Size of the got. */ - unsigned long got_size; - /* Number of symbols in syminfo. */ - int nsyms; - /* Additional symbol information (got offsets). */ - struct mod_arch_syminfo *syminfo; -}; - -#define MODULE_PROC_FAMILY "AVR32v1" - -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY - -#endif /* __ASM_AVR32_MODULE_H */ diff --git a/arch/avr32/include/asm/ocd.h b/arch/avr32/include/asm/ocd.h deleted file mode 100644 index 6bef09490235..000000000000 --- a/arch/avr32/include/asm/ocd.h +++ /dev/null @@ -1,543 +0,0 @@ -/* - * AVR32 OCD Interface and register definitions - * - * Copyright (C) 2004-2007 Atmel Corporation - * - * 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 __ASM_AVR32_OCD_H -#define __ASM_AVR32_OCD_H - -/* OCD Register offsets. Abbreviations used below: - * - * BP Breakpoint - * Comm Communication - * DT Data Trace - * PC Program Counter - * PID Process ID - * R/W Read/Write - * WP Watchpoint - */ -#define OCD_DID 0x0000 /* Device ID */ -#define OCD_DC 0x0008 /* Development Control */ -#define OCD_DS 0x0010 /* Development Status */ -#define OCD_RWCS 0x001c /* R/W Access Control */ -#define OCD_RWA 0x0024 /* R/W Access Address */ -#define OCD_RWD 0x0028 /* R/W Access Data */ -#define OCD_WT 0x002c /* Watchpoint Trigger */ -#define OCD_DTC 0x0034 /* Data Trace Control */ -#define OCD_DTSA0 0x0038 /* DT Start Addr Channel 0 */ -#define OCD_DTSA1 0x003c /* DT Start Addr Channel 1 */ -#define OCD_DTEA0 0x0048 /* DT End Addr Channel 0 */ -#define OCD_DTEA1 0x004c /* DT End Addr Channel 1 */ -#define OCD_BWC0A 0x0058 /* PC BP/WP Control 0A */ -#define OCD_BWC0B 0x005c /* PC BP/WP Control 0B */ -#define OCD_BWC1A 0x0060 /* PC BP/WP Control 1A */ -#define OCD_BWC1B 0x0064 /* PC BP/WP Control 1B */ -#define OCD_BWC2A 0x0068 /* PC BP/WP Control 2A */ -#define OCD_BWC2B 0x006c /* PC BP/WP Control 2B */ -#define OCD_BWC3A 0x0070 /* Data BP/WP Control 3A */ -#define OCD_BWC3B 0x0074 /* Data BP/WP Control 3B */ -#define OCD_BWA0A 0x0078 /* PC BP/WP Address 0A */ -#define OCD_BWA0B 0x007c /* PC BP/WP Address 0B */ -#define OCD_BWA1A 0x0080 /* PC BP/WP Address 1A */ -#define OCD_BWA1B 0x0084 /* PC BP/WP Address 1B */ -#define OCD_BWA2A 0x0088 /* PC BP/WP Address 2A */ -#define OCD_BWA2B 0x008c /* PC BP/WP Address 2B */ -#define OCD_BWA3A 0x0090 /* Data BP/WP Address 3A */ -#define OCD_BWA3B 0x0094 /* Data BP/WP Address 3B */ -#define OCD_NXCFG 0x0100 /* Nexus Configuration */ -#define OCD_DINST 0x0104 /* Debug Instruction */ -#define OCD_DPC 0x0108 /* Debug Program Counter */ -#define OCD_CPUCM 0x010c /* CPU Control Mask */ -#define OCD_DCCPU 0x0110 /* Debug Comm CPU */ -#define OCD_DCEMU 0x0114 /* Debug Comm Emulator */ -#define OCD_DCSR 0x0118 /* Debug Comm Status */ -#define OCD_PID 0x011c /* Ownership Trace PID */ -#define OCD_EPC0 0x0120 /* Event Pair Control 0 */ -#define OCD_EPC1 0x0124 /* Event Pair Control 1 */ -#define OCD_EPC2 0x0128 /* Event Pair Control 2 */ -#define OCD_EPC3 0x012c /* Event Pair Control 3 */ -#define OCD_AXC 0x0130 /* AUX port Control */ - -/* Bits in DID */ -#define OCD_DID_MID_START 1 -#define OCD_DID_MID_SIZE 11 -#define OCD_DID_PN_START 12 -#define OCD_DID_PN_SIZE 16 -#define OCD_DID_RN_START 28 -#define OCD_DID_RN_SIZE 4 - -/* Bits in DC */ -#define OCD_DC_TM_START 0 -#define OCD_DC_TM_SIZE 2 -#define OCD_DC_EIC_START 3 -#define OCD_DC_EIC_SIZE 2 -#define OCD_DC_OVC_START 5 -#define OCD_DC_OVC_SIZE 3 -#define OCD_DC_SS_BIT 8 -#define OCD_DC_DBR_BIT 12 -#define OCD_DC_DBE_BIT 13 -#define OCD_DC_EOS_START 20 -#define OCD_DC_EOS_SIZE 2 -#define OCD_DC_SQA_BIT 22 -#define OCD_DC_IRP_BIT 23 -#define OCD_DC_IFM_BIT 24 -#define OCD_DC_TOZ_BIT 25 -#define OCD_DC_TSR_BIT 26 -#define OCD_DC_RID_BIT 27 -#define OCD_DC_ORP_BIT 28 -#define OCD_DC_MM_BIT 29 -#define OCD_DC_RES_BIT 30 -#define OCD_DC_ABORT_BIT 31 - -/* Bits in DS */ -#define OCD_DS_SSS_BIT 0 -#define OCD_DS_SWB_BIT 1 -#define OCD_DS_HWB_BIT 2 -#define OCD_DS_HWE_BIT 3 -#define OCD_DS_STP_BIT 4 -#define OCD_DS_DBS_BIT 5 -#define OCD_DS_BP_START 8 -#define OCD_DS_BP_SIZE 8 -#define OCD_DS_INC_BIT 24 -#define OCD_DS_BOZ_BIT 25 -#define OCD_DS_DBA_BIT 26 -#define OCD_DS_EXB_BIT 27 -#define OCD_DS_NTBF_BIT 28 - -/* Bits in RWCS */ -#define OCD_RWCS_DV_BIT 0 -#define OCD_RWCS_ERR_BIT 1 -#define OCD_RWCS_CNT_START 2 -#define OCD_RWCS_CNT_SIZE 14 -#define OCD_RWCS_CRC_BIT 19 -#define OCD_RWCS_NTBC_START 20 -#define OCD_RWCS_NTBC_SIZE 2 -#define OCD_RWCS_NTE_BIT 22 -#define OCD_RWCS_NTAP_BIT 23 -#define OCD_RWCS_WRAPPED_BIT 24 -#define OCD_RWCS_CCTRL_START 25 -#define OCD_RWCS_CCTRL_SIZE 2 -#define OCD_RWCS_SZ_START 27 -#define OCD_RWCS_SZ_SIZE 3 -#define OCD_RWCS_RW_BIT 30 -#define OCD_RWCS_AC_BIT 31 - -/* Bits in RWA */ -#define OCD_RWA_RWA_START 0 -#define OCD_RWA_RWA_SIZE 32 - -/* Bits in RWD */ -#define OCD_RWD_RWD_START 0 -#define OCD_RWD_RWD_SIZE 32 - -/* Bits in WT */ -#define OCD_WT_DTE_START 20 -#define OCD_WT_DTE_SIZE 3 -#define OCD_WT_DTS_START 23 -#define OCD_WT_DTS_SIZE 3 -#define OCD_WT_PTE_START 26 -#define OCD_WT_PTE_SIZE 3 -#define OCD_WT_PTS_START 29 -#define OCD_WT_PTS_SIZE 3 - -/* Bits in DTC */ -#define OCD_DTC_T0WP_BIT 0 -#define OCD_DTC_T1WP_BIT 1 -#define OCD_DTC_ASID0EN_BIT 2 -#define OCD_DTC_ASID0_START 3 -#define OCD_DTC_ASID0_SIZE 8 -#define OCD_DTC_ASID1EN_BIT 11 -#define OCD_DTC_ASID1_START 12 -#define OCD_DTC_ASID1_SIZE 8 -#define OCD_DTC_RWT1_START 28 -#define OCD_DTC_RWT1_SIZE 2 -#define OCD_DTC_RWT0_START 30 -#define OCD_DTC_RWT0_SIZE 2 - -/* Bits in DTSA0 */ -#define OCD_DTSA0_DTSA_START 0 -#define OCD_DTSA0_DTSA_SIZE 32 - -/* Bits in DTSA1 */ -#define OCD_DTSA1_DTSA_START 0 -#define OCD_DTSA1_DTSA_SIZE 32 - -/* Bits in DTEA0 */ -#define OCD_DTEA0_DTEA_START 0 -#define OCD_DTEA0_DTEA_SIZE 32 - -/* Bits in DTEA1 */ -#define OCD_DTEA1_DTEA_START 0 -#define OCD_DTEA1_DTEA_SIZE 32 - -/* Bits in BWC0A */ -#define OCD_BWC0A_ASIDEN_BIT 0 -#define OCD_BWC0A_ASID_START 1 -#define OCD_BWC0A_ASID_SIZE 8 -#define OCD_BWC0A_EOC_BIT 14 -#define OCD_BWC0A_AME_BIT 25 -#define OCD_BWC0A_BWE_START 30 -#define OCD_BWC0A_BWE_SIZE 2 - -/* Bits in BWC0B */ -#define OCD_BWC0B_ASIDEN_BIT 0 -#define OCD_BWC0B_ASID_START 1 -#define OCD_BWC0B_ASID_SIZE 8 -#define OCD_BWC0B_EOC_BIT 14 -#define OCD_BWC0B_AME_BIT 25 -#define OCD_BWC0B_BWE_START 30 -#define OCD_BWC0B_BWE_SIZE 2 - -/* Bits in BWC1A */ -#define OCD_BWC1A_ASIDEN_BIT 0 -#define OCD_BWC1A_ASID_START 1 -#define OCD_BWC1A_ASID_SIZE 8 -#define OCD_BWC1A_EOC_BIT 14 -#define OCD_BWC1A_AME_BIT 25 -#define OCD_BWC1A_BWE_START 30 -#define OCD_BWC1A_BWE_SIZE 2 - -/* Bits in BWC1B */ -#define OCD_BWC1B_ASIDEN_BIT 0 -#define OCD_BWC1B_ASID_START 1 -#define OCD_BWC1B_ASID_SIZE 8 -#define OCD_BWC1B_EOC_BIT 14 -#define OCD_BWC1B_AME_BIT 25 -#define OCD_BWC1B_BWE_START 30 -#define OCD_BWC1B_BWE_SIZE 2 - -/* Bits in BWC2A */ -#define OCD_BWC2A_ASIDEN_BIT 0 -#define OCD_BWC2A_ASID_START 1 -#define OCD_BWC2A_ASID_SIZE 8 -#define OCD_BWC2A_EOC_BIT 14 -#define OCD_BWC2A_AMB_START 20 -#define OCD_BWC2A_AMB_SIZE 5 -#define OCD_BWC2A_AME_BIT 25 -#define OCD_BWC2A_BWE_START 30 -#define OCD_BWC2A_BWE_SIZE 2 - -/* Bits in BWC2B */ -#define OCD_BWC2B_ASIDEN_BIT 0 -#define OCD_BWC2B_ASID_START 1 -#define OCD_BWC2B_ASID_SIZE 8 -#define OCD_BWC2B_EOC_BIT 14 -#define OCD_BWC2B_AME_BIT 25 -#define OCD_BWC2B_BWE_START 30 -#define OCD_BWC2B_BWE_SIZE 2 - -/* Bits in BWC3A */ -#define OCD_BWC3A_ASIDEN_BIT 0 -#define OCD_BWC3A_ASID_START 1 -#define OCD_BWC3A_ASID_SIZE 8 -#define OCD_BWC3A_SIZE_START 9 -#define OCD_BWC3A_SIZE_SIZE 3 -#define OCD_BWC3A_EOC_BIT 14 -#define OCD_BWC3A_BWO_START 16 -#define OCD_BWC3A_BWO_SIZE 2 -#define OCD_BWC3A_BME_START 20 -#define OCD_BWC3A_BME_SIZE 4 -#define OCD_BWC3A_BRW_START 28 -#define OCD_BWC3A_BRW_SIZE 2 -#define OCD_BWC3A_BWE_START 30 -#define OCD_BWC3A_BWE_SIZE 2 - -/* Bits in BWC3B */ -#define OCD_BWC3B_ASIDEN_BIT 0 -#define OCD_BWC3B_ASID_START 1 -#define OCD_BWC3B_ASID_SIZE 8 -#define OCD_BWC3B_SIZE_START 9 -#define OCD_BWC3B_SIZE_SIZE 3 -#define OCD_BWC3B_EOC_BIT 14 -#define OCD_BWC3B_BWO_START 16 -#define OCD_BWC3B_BWO_SIZE 2 -#define OCD_BWC3B_BME_START 20 -#define OCD_BWC3B_BME_SIZE 4 -#define OCD_BWC3B_BRW_START 28 -#define OCD_BWC3B_BRW_SIZE 2 -#define OCD_BWC3B_BWE_START 30 -#define OCD_BWC3B_BWE_SIZE 2 - -/* Bits in BWA0A */ -#define OCD_BWA0A_BWA_START 0 -#define OCD_BWA0A_BWA_SIZE 32 - -/* Bits in BWA0B */ -#define OCD_BWA0B_BWA_START 0 -#define OCD_BWA0B_BWA_SIZE 32 - -/* Bits in BWA1A */ -#define OCD_BWA1A_BWA_START 0 -#define OCD_BWA1A_BWA_SIZE 32 - -/* Bits in BWA1B */ -#define OCD_BWA1B_BWA_START 0 -#define OCD_BWA1B_BWA_SIZE 32 - -/* Bits in BWA2A */ -#define OCD_BWA2A_BWA_START 0 -#define OCD_BWA2A_BWA_SIZE 32 - -/* Bits in BWA2B */ -#define OCD_BWA2B_BWA_START 0 -#define OCD_BWA2B_BWA_SIZE 32 - -/* Bits in BWA3A */ -#define OCD_BWA3A_BWA_START 0 -#define OCD_BWA3A_BWA_SIZE 32 - -/* Bits in BWA3B */ -#define OCD_BWA3B_BWA_START 0 -#define OCD_BWA3B_BWA_SIZE 32 - -/* Bits in NXCFG */ -#define OCD_NXCFG_NXARCH_START 0 -#define OCD_NXCFG_NXARCH_SIZE 4 -#define OCD_NXCFG_NXOCD_START 4 -#define OCD_NXCFG_NXOCD_SIZE 4 -#define OCD_NXCFG_NXPCB_START 8 -#define OCD_NXCFG_NXPCB_SIZE 4 -#define OCD_NXCFG_NXDB_START 12 -#define OCD_NXCFG_NXDB_SIZE 4 -#define OCD_NXCFG_MXMSEO_BIT 16 -#define OCD_NXCFG_NXMDO_START 17 -#define OCD_NXCFG_NXMDO_SIZE 4 -#define OCD_NXCFG_NXPT_BIT 21 -#define OCD_NXCFG_NXOT_BIT 22 -#define OCD_NXCFG_NXDWT_BIT 23 -#define OCD_NXCFG_NXDRT_BIT 24 -#define OCD_NXCFG_NXDTC_START 25 -#define OCD_NXCFG_NXDTC_SIZE 3 -#define OCD_NXCFG_NXDMA_BIT 28 - -/* Bits in DINST */ -#define OCD_DINST_DINST_START 0 -#define OCD_DINST_DINST_SIZE 32 - -/* Bits in CPUCM */ -#define OCD_CPUCM_BEM_BIT 1 -#define OCD_CPUCM_FEM_BIT 2 -#define OCD_CPUCM_REM_BIT 3 -#define OCD_CPUCM_IBEM_BIT 4 -#define OCD_CPUCM_IEEM_BIT 5 - -/* Bits in DCCPU */ -#define OCD_DCCPU_DATA_START 0 -#define OCD_DCCPU_DATA_SIZE 32 - -/* Bits in DCEMU */ -#define OCD_DCEMU_DATA_START 0 -#define OCD_DCEMU_DATA_SIZE 32 - -/* Bits in DCSR */ -#define OCD_DCSR_CPUD_BIT 0 -#define OCD_DCSR_EMUD_BIT 1 - -/* Bits in PID */ -#define OCD_PID_PROCESS_START 0 -#define OCD_PID_PROCESS_SIZE 32 - -/* Bits in EPC0 */ -#define OCD_EPC0_RNG_START 0 -#define OCD_EPC0_RNG_SIZE 2 -#define OCD_EPC0_CE_BIT 4 -#define OCD_EPC0_ECNT_START 16 -#define OCD_EPC0_ECNT_SIZE 16 - -/* Bits in EPC1 */ -#define OCD_EPC1_RNG_START 0 -#define OCD_EPC1_RNG_SIZE 2 -#define OCD_EPC1_ATB_BIT 5 -#define OCD_EPC1_AM_BIT 6 - -/* Bits in EPC2 */ -#define OCD_EPC2_RNG_START 0 -#define OCD_EPC2_RNG_SIZE 2 -#define OCD_EPC2_DB_START 2 -#define OCD_EPC2_DB_SIZE 2 - -/* Bits in EPC3 */ -#define OCD_EPC3_RNG_START 0 -#define OCD_EPC3_RNG_SIZE 2 -#define OCD_EPC3_DWE_BIT 2 - -/* Bits in AXC */ -#define OCD_AXC_DIV_START 0 -#define OCD_AXC_DIV_SIZE 4 -#define OCD_AXC_AXE_BIT 8 -#define OCD_AXC_AXS_BIT 9 -#define OCD_AXC_DDR_BIT 10 -#define OCD_AXC_LS_BIT 11 -#define OCD_AXC_REX_BIT 12 -#define OCD_AXC_REXTEN_BIT 13 - -/* Constants for DC:EIC */ -#define OCD_EIC_PROGRAM_AND_DATA_TRACE 0 -#define OCD_EIC_BREAKPOINT 1 -#define OCD_EIC_NOP 2 - -/* Constants for DC:OVC */ -#define OCD_OVC_OVERRUN 0 -#define OCD_OVC_DELAY_CPU_BTM 1 -#define OCD_OVC_DELAY_CPU_DTM 2 -#define OCD_OVC_DELAY_CPU_BTM_DTM 3 - -/* Constants for DC:EOS */ -#define OCD_EOS_NOP 0 -#define OCD_EOS_DEBUG_MODE 1 -#define OCD_EOS_BREAKPOINT_WATCHPOINT 2 -#define OCD_EOS_THQ 3 - -/* Constants for RWCS:NTBC */ -#define OCD_NTBC_OVERWRITE 0 -#define OCD_NTBC_DISABLE 1 -#define OCD_NTBC_BREAKPOINT 2 - -/* Constants for RWCS:CCTRL */ -#define OCD_CCTRL_AUTO 0 -#define OCD_CCTRL_CACHED 1 -#define OCD_CCTRL_UNCACHED 2 - -/* Constants for RWCS:SZ */ -#define OCD_SZ_BYTE 0 -#define OCD_SZ_HALFWORD 1 -#define OCD_SZ_WORD 2 - -/* Constants for WT:PTS */ -#define OCD_PTS_DISABLED 0 -#define OCD_PTS_PROGRAM_0B 1 -#define OCD_PTS_PROGRAM_1A 2 -#define OCD_PTS_PROGRAM_1B 3 -#define OCD_PTS_PROGRAM_2A 4 -#define OCD_PTS_PROGRAM_2B 5 -#define OCD_PTS_DATA_3A 6 -#define OCD_PTS_DATA_3B 7 - -/* Constants for DTC:RWT1 */ -#define OCD_RWT1_NO_TRACE 0 -#define OCD_RWT1_DATA_READ 1 -#define OCD_RWT1_DATA_WRITE 2 -#define OCD_RWT1_DATA_READ_WRITE 3 - -/* Constants for DTC:RWT0 */ -#define OCD_RWT0_NO_TRACE 0 -#define OCD_RWT0_DATA_READ 1 -#define OCD_RWT0_DATA_WRITE 2 -#define OCD_RWT0_DATA_READ_WRITE 3 - -/* Constants for BWC0A:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC0B:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC1A:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC1B:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC2A:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC2B:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC3A:SIZE */ -#define OCD_SIZE_BYTE_ACCESS 4 -#define OCD_SIZE_HALFWORD_ACCESS 5 -#define OCD_SIZE_WORD_ACCESS 6 -#define OCD_SIZE_DOUBLE_WORD_ACCESS 7 - -/* Constants for BWC3A:BRW */ -#define OCD_BRW_READ_BREAK 0 -#define OCD_BRW_WRITE_BREAK 1 -#define OCD_BRW_ANY_ACCES_BREAK 2 - -/* Constants for BWC3A:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for BWC3B:SIZE */ -#define OCD_SIZE_BYTE_ACCESS 4 -#define OCD_SIZE_HALFWORD_ACCESS 5 -#define OCD_SIZE_WORD_ACCESS 6 -#define OCD_SIZE_DOUBLE_WORD_ACCESS 7 - -/* Constants for BWC3B:BRW */ -#define OCD_BRW_READ_BREAK 0 -#define OCD_BRW_WRITE_BREAK 1 -#define OCD_BRW_ANY_ACCES_BREAK 2 - -/* Constants for BWC3B:BWE */ -#define OCD_BWE_DISABLED 0 -#define OCD_BWE_BREAKPOINT_ENABLED 1 -#define OCD_BWE_WATCHPOINT_ENABLED 3 - -/* Constants for EPC0:RNG */ -#define OCD_RNG_DISABLED 0 -#define OCD_RNG_EXCLUSIVE 1 -#define OCD_RNG_INCLUSIVE 2 - -/* Constants for EPC1:RNG */ -#define OCD_RNG_DISABLED 0 -#define OCD_RNG_EXCLUSIVE 1 -#define OCD_RNG_INCLUSIVE 2 - -/* Constants for EPC2:RNG */ -#define OCD_RNG_DISABLED 0 -#define OCD_RNG_EXCLUSIVE 1 -#define OCD_RNG_INCLUSIVE 2 - -/* Constants for EPC2:DB */ -#define OCD_DB_DISABLED 0 -#define OCD_DB_CHAINED_B 1 -#define OCD_DB_CHAINED_A 2 -#define OCD_DB_AHAINED_A_AND_B 3 - -/* Constants for EPC3:RNG */ -#define OCD_RNG_DISABLED 0 -#define OCD_RNG_EXCLUSIVE 1 -#define OCD_RNG_INCLUSIVE 2 - -#ifndef __ASSEMBLER__ - -/* Register access macros */ -static inline unsigned long __ocd_read(unsigned int reg) -{ - return __builtin_mfdr(reg); -} - -static inline void __ocd_write(unsigned int reg, unsigned long value) -{ - __builtin_mtdr(reg, value); -} - -#define ocd_read(reg) __ocd_read(OCD_##reg) -#define ocd_write(reg, value) __ocd_write(OCD_##reg, value) - -struct task_struct; - -void ocd_enable(struct task_struct *child); -void ocd_disable(struct task_struct *child); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __ASM_AVR32_OCD_H */ diff --git a/arch/avr32/include/asm/page.h b/arch/avr32/include/asm/page.h deleted file mode 100644 index c5d2a3e2c62f..000000000000 --- a/arch/avr32/include/asm/page.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_PAGE_H -#define __ASM_AVR32_PAGE_H - -#include <linux/const.h> - -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) -#define PTE_MASK PAGE_MASK - -#ifndef __ASSEMBLY__ - -#include <asm/addrspace.h> - -extern void clear_page(void *to); -extern void copy_page(void *to, void *from); - -#define clear_user_page(page, vaddr, pg) clear_page(page) -#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) - -/* - * These are used to make use of C type-checking.. - */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; -typedef struct page *pgtable_t; - -#define pte_val(x) ((x).pte) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) }) -#define __pgd(x) ((pgd_t) { (x) }) -#define __pgprot(x) ((pgprot_t) { (x) }) - -/* FIXME: These should be removed soon */ -extern unsigned long memory_start, memory_end; - -/* Pure 2^n version of get_order */ -static inline int get_order(unsigned long size) -{ - unsigned lz; - - size = (size - 1) >> PAGE_SHIFT; - asm("clz %0, %1" : "=r"(lz) : "r"(size)); - return 32 - lz; -} - -#endif /* !__ASSEMBLY__ */ - -/* - * The hardware maps the virtual addresses 0x80000000 -> 0x9fffffff - * permanently to the physical addresses 0x00000000 -> 0x1fffffff when - * segmentation is enabled. We want to make use of this in order to - * minimize TLB pressure. - */ -#define PAGE_OFFSET (0x80000000UL) - -/* - * ALSA uses virt_to_page() on DMA pages, which I'm not entirely sure - * is a good idea. Anyway, we can't simply subtract PAGE_OFFSET here - * in that case, so we'll have to mask out the three most significant - * bits of the address instead... - * - * What's the difference between __pa() and virt_to_phys() anyway? - */ -#define __pa(x) PHYSADDR(x) -#define __va(x) ((void *)(P1SEGADDR(x))) - -#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) - -#define phys_to_page(phys) (pfn_to_page(phys >> PAGE_SHIFT)) -#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) - -#ifndef CONFIG_NEED_MULTIPLE_NODES - -#define ARCH_PFN_OFFSET (CONFIG_PHYS_OFFSET >> PAGE_SHIFT) - -#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < (ARCH_PFN_OFFSET + max_mapnr)) -#endif /* CONFIG_NEED_MULTIPLE_NODES */ - -#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) - -#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -/* - * Memory above this physical address will be considered highmem. - */ -#define HIGHMEM_START 0x20000000UL - -#include <asm-generic/memory_model.h> - -#endif /* __ASM_AVR32_PAGE_H */ diff --git a/arch/avr32/include/asm/pci.h b/arch/avr32/include/asm/pci.h deleted file mode 100644 index 0f5f134b896a..000000000000 --- a/arch/avr32/include/asm/pci.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_AVR32_PCI_H__ -#define __ASM_AVR32_PCI_H__ - -/* We don't support PCI yet, but some drivers require this file anyway */ - -#define PCI_DMA_BUS_IS_PHYS (1) - -#endif /* __ASM_AVR32_PCI_H__ */ diff --git a/arch/avr32/include/asm/pgalloc.h b/arch/avr32/include/asm/pgalloc.h deleted file mode 100644 index db039cb368be..000000000000 --- a/arch/avr32/include/asm/pgalloc.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_PGALLOC_H -#define __ASM_AVR32_PGALLOC_H - -#include <linux/mm.h> -#include <linux/quicklist.h> -#include <asm/page.h> -#include <asm/pgtable.h> - -#define QUICK_PGD 0 /* Preserve kernel mappings over free */ -#define QUICK_PT 1 /* Zero on free */ - -static inline void pmd_populate_kernel(struct mm_struct *mm, - pmd_t *pmd, pte_t *pte) -{ - set_pmd(pmd, __pmd((unsigned long)pte)); -} - -static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, - pgtable_t pte) -{ - set_pmd(pmd, __pmd((unsigned long)page_address(pte))); -} -#define pmd_pgtable(pmd) pmd_page(pmd) - -static inline void pgd_ctor(void *x) -{ - pgd_t *pgd = x; - - memcpy(pgd + USER_PTRS_PER_PGD, - swapper_pg_dir + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); -} - -/* - * Allocate and free page tables - */ -static inline pgd_t *pgd_alloc(struct mm_struct *mm) -{ - return quicklist_alloc(QUICK_PGD, GFP_KERNEL, pgd_ctor); -} - -static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) -{ - quicklist_free(QUICK_PGD, NULL, pgd); -} - -static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, - unsigned long address) -{ - return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL); -} - -static inline pgtable_t pte_alloc_one(struct mm_struct *mm, - unsigned long address) -{ - struct page *page; - void *pg; - - pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL); - if (!pg) - return NULL; - - page = virt_to_page(pg); - if (!pgtable_page_ctor(page)) { - quicklist_free(QUICK_PT, NULL, pg); - return NULL; - } - - return page; -} - -static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) -{ - quicklist_free(QUICK_PT, NULL, pte); -} - -static inline void pte_free(struct mm_struct *mm, pgtable_t pte) -{ - pgtable_page_dtor(pte); - quicklist_free_page(QUICK_PT, NULL, pte); -} - -#define __pte_free_tlb(tlb,pte,addr) \ -do { \ - pgtable_page_dtor(pte); \ - tlb_remove_page((tlb), pte); \ -} while (0) - -static inline void check_pgt_cache(void) -{ - quicklist_trim(QUICK_PGD, NULL, 25, 16); - quicklist_trim(QUICK_PT, NULL, 25, 16); -} - -#endif /* __ASM_AVR32_PGALLOC_H */ diff --git a/arch/avr32/include/asm/pgtable-2level.h b/arch/avr32/include/asm/pgtable-2level.h deleted file mode 100644 index 425dd567b5b9..000000000000 --- a/arch/avr32/include/asm/pgtable-2level.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_PGTABLE_2LEVEL_H -#define __ASM_AVR32_PGTABLE_2LEVEL_H - -#include <asm-generic/pgtable-nopmd.h> - -/* - * Traditional 2-level paging structure - */ -#define PGDIR_SHIFT 22 -#define PTRS_PER_PGD 1024 - -#define PTRS_PER_PTE 1024 - -#ifndef __ASSEMBLY__ -#define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -#define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) - -/* - * Certain architectures need to do special things when PTEs - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#define set_pte(pteptr, pteval) (*(pteptr) = pteval) -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep, pteval) - -/* - * (pmds are folded into pgds so this doesn't get actually called, - * but the define is needed for a generic inline function.) - */ -#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) - -#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) -#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) -#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_AVR32_PGTABLE_2LEVEL_H */ diff --git a/arch/avr32/include/asm/pgtable.h b/arch/avr32/include/asm/pgtable.h deleted file mode 100644 index 35800664076e..000000000000 --- a/arch/avr32/include/asm/pgtable.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_PGTABLE_H -#define __ASM_AVR32_PGTABLE_H - -#include <asm/addrspace.h> - -#ifndef __ASSEMBLY__ -#include <linux/sched.h> - -#endif /* !__ASSEMBLY__ */ - -/* - * Use two-level page tables just as the i386 (without PAE) - */ -#include <asm/pgtable-2level.h> - -/* - * The following code might need some cleanup when the values are - * final... - */ -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) - -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) -#define FIRST_USER_ADDRESS 0UL - -#ifndef __ASSEMBLY__ -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -extern void paging_init(void); - -/* - * ZERO_PAGE is a global shared page that is always zero: used for - * zero-mapped memory areas etc. - */ -extern struct page *empty_zero_page; -#define ZERO_PAGE(vaddr) (empty_zero_page) - -/* - * Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8 MiB value just means that there will be a 8 MiB "hole" - * after the uncached physical memory (P2 segment) until the vmalloc - * area starts. That means that any out-of-bounds memory accesses will - * hopefully be caught; we don't know if the end of the P1/P2 segments - * are actually used for anything, but it is anyway safer to let the - * MMU catch these kinds of errors than to rely on the memory bus. - * - * A "hole" of the same size is added to the end of the P3 segment as - * well. It might seem wasteful to use 16 MiB of virtual address space - * on this, but we do have 512 MiB of it... - * - * The vmalloc() routines leave a hole of 4 KiB between each vmalloced - * area for the same reason. - */ -#define VMALLOC_OFFSET (8 * 1024 * 1024) -#define VMALLOC_START (P3SEG + VMALLOC_OFFSET) -#define VMALLOC_END (P4SEG - VMALLOC_OFFSET) -#endif /* !__ASSEMBLY__ */ - -/* - * Page flags. Some of these flags are not directly supported by - * hardware, so we have to emulate them. - */ -#define _TLBEHI_BIT_VALID 9 -#define _TLBEHI_VALID (1 << _TLBEHI_BIT_VALID) - -#define _PAGE_BIT_WT 0 /* W-bit : write-through */ -#define _PAGE_BIT_DIRTY 1 /* D-bit : page changed */ -#define _PAGE_BIT_SZ0 2 /* SZ0-bit : Size of page */ -#define _PAGE_BIT_SZ1 3 /* SZ1-bit : Size of page */ -#define _PAGE_BIT_EXECUTE 4 /* X-bit : execute access allowed */ -#define _PAGE_BIT_RW 5 /* AP0-bit : write access allowed */ -#define _PAGE_BIT_USER 6 /* AP1-bit : user space access allowed */ -#define _PAGE_BIT_BUFFER 7 /* B-bit : bufferable */ -#define _PAGE_BIT_GLOBAL 8 /* G-bit : global (ignore ASID) */ -#define _PAGE_BIT_CACHABLE 9 /* C-bit : cachable */ - -/* If we drop support for 1K pages, we get two extra bits */ -#define _PAGE_BIT_PRESENT 10 -#define _PAGE_BIT_ACCESSED 11 /* software: page was accessed */ - -#define _PAGE_WT (1 << _PAGE_BIT_WT) -#define _PAGE_DIRTY (1 << _PAGE_BIT_DIRTY) -#define _PAGE_EXECUTE (1 << _PAGE_BIT_EXECUTE) -#define _PAGE_RW (1 << _PAGE_BIT_RW) -#define _PAGE_USER (1 << _PAGE_BIT_USER) -#define _PAGE_BUFFER (1 << _PAGE_BIT_BUFFER) -#define _PAGE_GLOBAL (1 << _PAGE_BIT_GLOBAL) -#define _PAGE_CACHABLE (1 << _PAGE_BIT_CACHABLE) - -/* Software flags */ -#define _PAGE_ACCESSED (1 << _PAGE_BIT_ACCESSED) -#define _PAGE_PRESENT (1 << _PAGE_BIT_PRESENT) - -/* - * Page types, i.e. sizes. _PAGE_TYPE_NONE corresponds to what is - * usually called _PAGE_PROTNONE on other architectures. - * - * XXX: Find out if _PAGE_PROTNONE is equivalent with !_PAGE_USER. If - * so, we can encode all possible page sizes (although we can't really - * support 1K pages anyway due to the _PAGE_PRESENT and _PAGE_ACCESSED - * bits) - * - */ -#define _PAGE_TYPE_MASK ((1 << _PAGE_BIT_SZ0) | (1 << _PAGE_BIT_SZ1)) -#define _PAGE_TYPE_NONE (0 << _PAGE_BIT_SZ0) -#define _PAGE_TYPE_SMALL (1 << _PAGE_BIT_SZ0) -#define _PAGE_TYPE_MEDIUM (2 << _PAGE_BIT_SZ0) -#define _PAGE_TYPE_LARGE (3 << _PAGE_BIT_SZ0) - -/* - * Mask which drop software flags. We currently can't handle more than - * 512 MiB of physical memory, so we can use bits 29-31 for other - * stuff. With a fixed 4K page size, we can use bits 10-11 as well as - * bits 2-3 (SZ) - */ -#define _PAGE_FLAGS_HARDWARE_MASK 0xfffff3ff - -#define _PAGE_FLAGS_CACHE_MASK (_PAGE_CACHABLE | _PAGE_BUFFER | _PAGE_WT) - -/* Flags that may be modified by software */ -#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY \ - | _PAGE_FLAGS_CACHE_MASK) - -#define _PAGE_FLAGS_READ (_PAGE_CACHABLE | _PAGE_BUFFER) -#define _PAGE_FLAGS_WRITE (_PAGE_FLAGS_READ | _PAGE_RW | _PAGE_DIRTY) - -#define _PAGE_NORMAL(x) __pgprot((x) | _PAGE_PRESENT | _PAGE_TYPE_SMALL \ - | _PAGE_ACCESSED) - -#define PAGE_NONE (_PAGE_ACCESSED | _PAGE_TYPE_NONE) -#define PAGE_READ (_PAGE_FLAGS_READ | _PAGE_USER) -#define PAGE_EXEC (_PAGE_FLAGS_READ | _PAGE_EXECUTE | _PAGE_USER) -#define PAGE_WRITE (_PAGE_FLAGS_WRITE | _PAGE_USER) -#define PAGE_KERNEL _PAGE_NORMAL(_PAGE_FLAGS_WRITE | _PAGE_EXECUTE | _PAGE_GLOBAL) -#define PAGE_KERNEL_RO _PAGE_NORMAL(_PAGE_FLAGS_READ | _PAGE_EXECUTE | _PAGE_GLOBAL) - -#define _PAGE_P(x) _PAGE_NORMAL((x) & ~(_PAGE_RW | _PAGE_DIRTY)) -#define _PAGE_S(x) _PAGE_NORMAL(x) - -#define PAGE_COPY _PAGE_P(PAGE_WRITE | PAGE_READ) -#define PAGE_SHARED _PAGE_S(PAGE_WRITE | PAGE_READ) - -#ifndef __ASSEMBLY__ -/* - * The hardware supports flags for write- and execute access. Read is - * always allowed if the page is loaded into the TLB, so the "-w-", - * "--x" and "-wx" mappings are implemented as "rw-", "r-x" and "rwx", - * respectively. - * - * The "---" case is handled by software; the page will simply not be - * loaded into the TLB if the page type is _PAGE_TYPE_NONE. - */ - -#define __P000 __pgprot(PAGE_NONE) -#define __P001 _PAGE_P(PAGE_READ) -#define __P010 _PAGE_P(PAGE_WRITE) -#define __P011 _PAGE_P(PAGE_WRITE | PAGE_READ) -#define __P100 _PAGE_P(PAGE_EXEC) -#define __P101 _PAGE_P(PAGE_EXEC | PAGE_READ) -#define __P110 _PAGE_P(PAGE_EXEC | PAGE_WRITE) -#define __P111 _PAGE_P(PAGE_EXEC | PAGE_WRITE | PAGE_READ) - -#define __S000 __pgprot(PAGE_NONE) -#define __S001 _PAGE_S(PAGE_READ) -#define __S010 _PAGE_S(PAGE_WRITE) -#define __S011 _PAGE_S(PAGE_WRITE | PAGE_READ) -#define __S100 _PAGE_S(PAGE_EXEC) -#define __S101 _PAGE_S(PAGE_EXEC | PAGE_READ) -#define __S110 _PAGE_S(PAGE_EXEC | PAGE_WRITE) -#define __S111 _PAGE_S(PAGE_EXEC | PAGE_WRITE | PAGE_READ) - -#define pte_none(x) (!pte_val(x)) -#define pte_present(x) (pte_val(x) & _PAGE_PRESENT) - -#define pte_clear(mm,addr,xp) \ - do { \ - set_pte_at(mm, addr, xp, __pte(0)); \ - } while (0) - -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -static inline int pte_write(pte_t pte) -{ - return pte_val(pte) & _PAGE_RW; -} -static inline int pte_dirty(pte_t pte) -{ - return pte_val(pte) & _PAGE_DIRTY; -} -static inline int pte_young(pte_t pte) -{ - return pte_val(pte) & _PAGE_ACCESSED; -} -static inline int pte_special(pte_t pte) -{ - return 0; -} - -/* Mutator functions for PTE bits */ -static inline pte_t pte_wrprotect(pte_t pte) -{ - set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); - return pte; -} -static inline pte_t pte_mkclean(pte_t pte) -{ - set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); - return pte; -} -static inline pte_t pte_mkold(pte_t pte) -{ - set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); - return pte; -} -static inline pte_t pte_mkwrite(pte_t pte) -{ - set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); - return pte; -} -static inline pte_t pte_mkdirty(pte_t pte) -{ - set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); - return pte; -} -static inline pte_t pte_mkyoung(pte_t pte) -{ - set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); - return pte; -} -static inline pte_t pte_mkspecial(pte_t pte) -{ - return pte; -} - -#define pmd_none(x) (!pmd_val(x)) -#define pmd_present(x) (pmd_val(x)) - -static inline void pmd_clear(pmd_t *pmdp) -{ - set_pmd(pmdp, __pmd(0)); -} - -#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK) - -/* - * Permanent address of a page. We don't support highmem, so this is - * trivial. - */ -#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -#define pte_page(x) (pfn_to_page(pte_pfn(x))) - -/* - * Mark the prot value as uncacheable and unbufferable - */ -#define pgprot_noncached(prot) \ - __pgprot(pgprot_val(prot) & ~(_PAGE_BUFFER | _PAGE_CACHABLE)) - -/* - * Mark the prot value as uncacheable but bufferable - */ -#define pgprot_writecombine(prot) \ - __pgprot((pgprot_val(prot) & ~_PAGE_CACHABLE) | _PAGE_BUFFER) - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - * - * extern pte_t mk_pte(struct page *page, pgprot_t pgprot) - */ -#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) - -static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ - set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) - | pgprot_val(newprot))); - return pte; -} - -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - -#define pmd_page_vaddr(pmd) pmd_val(pmd) -#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) - -/* to find an entry in a page-table-directory. */ -#define pgd_index(address) (((address) >> PGDIR_SHIFT) \ - & (PTRS_PER_PGD - 1)) -#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) - -/* to find an entry in a kernel page-table-directory */ -#define pgd_offset_k(address) pgd_offset(&init_mm, address) - -/* Find an entry in the third-level page table.. */ -#define pte_index(address) \ - ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) -#define pte_offset(dir, address) \ - ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) -#define pte_offset_kernel(dir, address) \ - ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) -#define pte_offset_map(dir, address) pte_offset_kernel(dir, address) -#define pte_unmap(pte) do { } while (0) - -struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t *ptep); - -/* - * Encode and decode a swap entry - * - * Constraints: - * _PAGE_TYPE_* at bits 2-3 (for emulating _PAGE_PROTNONE) - * _PAGE_PRESENT at bit 10 - * - * We encode the type into bits 4-9 and offset into bits 11-31. This - * gives us a 21 bits offset, or 2**21 * 4K = 8G usable swap space per - * device, and 64 possible types. - * - * NOTE: We should set ZEROs at the position of _PAGE_PRESENT - * and _PAGE_PROTNONE bits - */ -#define __swp_type(x) (((x).val >> 4) & 0x3f) -#define __swp_offset(x) ((x).val >> 11) -#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 4) | ((offset) << 11) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - -typedef pte_t *pte_addr_t; - -#define kern_addr_valid(addr) (1) - -/* No page table caches to initialize (?) */ -#define pgtable_cache_init() do { } while(0) - -#include <asm-generic/pgtable.h> - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_AVR32_PGTABLE_H */ diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h deleted file mode 100644 index 972adcc1e8f4..000000000000 --- a/arch/avr32/include/asm/processor.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_PROCESSOR_H -#define __ASM_AVR32_PROCESSOR_H - -#include <asm/page.h> -#include <asm/cache.h> - -#define TASK_SIZE 0x80000000 - -#ifdef __KERNEL__ -#define STACK_TOP TASK_SIZE -#define STACK_TOP_MAX STACK_TOP -#endif - -#ifndef __ASSEMBLY__ - -static inline void *current_text_addr(void) -{ - register void *pc asm("pc"); - return pc; -} - -enum arch_type { - ARCH_AVR32A, - ARCH_AVR32B, - ARCH_MAX -}; - -enum cpu_type { - CPU_MORGAN, - CPU_AT32AP, - CPU_MAX -}; - -enum tlb_config { - TLB_NONE, - TLB_SPLIT, - TLB_UNIFIED, - TLB_INVALID -}; - -#define AVR32_FEATURE_RMW (1 << 0) -#define AVR32_FEATURE_DSP (1 << 1) -#define AVR32_FEATURE_SIMD (1 << 2) -#define AVR32_FEATURE_OCD (1 << 3) -#define AVR32_FEATURE_PCTR (1 << 4) -#define AVR32_FEATURE_JAVA (1 << 5) -#define AVR32_FEATURE_FPU (1 << 6) - -struct avr32_cpuinfo { - struct clk *clk; - unsigned long loops_per_jiffy; - enum arch_type arch_type; - enum cpu_type cpu_type; - unsigned short arch_revision; - unsigned short cpu_revision; - enum tlb_config tlb_config; - unsigned long features; - u32 device_id; - - struct cache_info icache; - struct cache_info dcache; -}; - -static inline unsigned int avr32_get_manufacturer_id(struct avr32_cpuinfo *cpu) -{ - return (cpu->device_id >> 1) & 0x7f; -} -static inline unsigned int avr32_get_product_number(struct avr32_cpuinfo *cpu) -{ - return (cpu->device_id >> 12) & 0xffff; -} -static inline unsigned int avr32_get_chip_revision(struct avr32_cpuinfo *cpu) -{ - return (cpu->device_id >> 28) & 0x0f; -} - -extern struct avr32_cpuinfo boot_cpu_data; - -/* No SMP support so far */ -#define current_cpu_data boot_cpu_data - -/* This decides where the kernel will search for a free chunk of vm - * space during mmap's - */ -#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) - -#define cpu_relax() barrier() -#define cpu_sync_pipeline() asm volatile("sub pc, -2" : : : "memory") - -struct cpu_context { - unsigned long sr; - unsigned long pc; - unsigned long ksp; /* Kernel stack pointer */ - unsigned long r7; - unsigned long r6; - unsigned long r5; - unsigned long r4; - unsigned long r3; - unsigned long r2; - unsigned long r1; - unsigned long r0; -}; - -/* This struct contains the CPU context as stored by switch_to() */ -struct thread_struct { - struct cpu_context cpu_context; - unsigned long single_step_addr; - u16 single_step_insn; -}; - -#define INIT_THREAD { \ - .cpu_context = { \ - .ksp = sizeof(init_stack) + (long)&init_stack, \ - }, \ -} - -/* - * Do necessary setup to start up a newly executed thread. - */ -#define start_thread(regs, new_pc, new_sp) \ - do { \ - memset(regs, 0, sizeof(*regs)); \ - regs->sr = MODE_USER; \ - regs->pc = new_pc & ~1; \ - regs->sp = new_sp; \ - } while(0) - -struct task_struct; - -/* Free all resources held by a thread */ -extern void release_thread(struct task_struct *); - -/* Return saved PC of a blocked thread */ -#define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) - -struct pt_regs; -extern unsigned long get_wchan(struct task_struct *p); -extern void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl); -extern void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp, - struct pt_regs *regs, const char *log_lvl); - -#define task_pt_regs(p) \ - ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) - -#define KSTK_EIP(tsk) ((tsk)->thread.cpu_context.pc) -#define KSTK_ESP(tsk) ((tsk)->thread.cpu_context.ksp) - -#define ARCH_HAS_PREFETCH - -static inline void prefetch(const void *x) -{ - const char *c = x; - asm volatile("pref %0" : : "r"(c)); -} -#define PREFETCH_STRIDE L1_CACHE_BYTES - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_AVR32_PROCESSOR_H */ diff --git a/arch/avr32/include/asm/ptrace.h b/arch/avr32/include/asm/ptrace.h deleted file mode 100644 index 630e4f9bf5f0..000000000000 --- a/arch/avr32/include/asm/ptrace.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_PTRACE_H -#define __ASM_AVR32_PTRACE_H - -#include <uapi/asm/ptrace.h> - -#ifndef __ASSEMBLY__ - -#include <asm/ocd.h> - -#define arch_has_single_step() (1) - -#define arch_ptrace_attach(child) ocd_enable(child) - -#define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER) -#define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) instruction_pointer(regs) -#define user_stack_pointer(regs) ((regs)->sp) - -static __inline__ int valid_user_regs(struct pt_regs *regs) -{ - /* - * Some of the Java bits might be acceptable if/when we - * implement some support for that stuff... - */ - if ((regs->sr & 0xffff0000) == 0) - return 1; - - /* - * Force status register flags to be sane and report this - * illegal behaviour... - */ - regs->sr &= 0x0000ffff; - return 0; -} - - -#endif /* ! __ASSEMBLY__ */ -#endif /* __ASM_AVR32_PTRACE_H */ diff --git a/arch/avr32/include/asm/serial.h b/arch/avr32/include/asm/serial.h deleted file mode 100644 index 5ecaebc22b02..000000000000 --- a/arch/avr32/include/asm/serial.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _ASM_SERIAL_H -#define _ASM_SERIAL_H - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ -#define BASE_BAUD (1843200 / 16) - -#endif /* _ASM_SERIAL_H */ diff --git a/arch/avr32/include/asm/setup.h b/arch/avr32/include/asm/setup.h deleted file mode 100644 index 73490ae0c476..000000000000 --- a/arch/avr32/include/asm/setup.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * Based on linux/include/asm-arm/setup.h - * Copyright (C) 1997-1999 Russell King - * - * 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 __ASM_AVR32_SETUP_H__ -#define __ASM_AVR32_SETUP_H__ - -#include <uapi/asm/setup.h> - - -/* Magic number indicating that a tag table is present */ -#define ATAG_MAGIC 0xa2a25441 - -#ifndef __ASSEMBLY__ - -/* - * Generic memory range, used by several tags. - * - * addr is always physical. - * size is measured in bytes. - * next is for use by the OS, e.g. for grouping regions into - * linked lists. - */ -struct tag_mem_range { - u32 addr; - u32 size; - struct tag_mem_range * next; -}; - -/* The list ends with an ATAG_NONE node. */ -#define ATAG_NONE 0x00000000 - -struct tag_header { - u32 size; - u32 tag; -}; - -/* The list must start with an ATAG_CORE node */ -#define ATAG_CORE 0x54410001 - -struct tag_core { - u32 flags; - u32 pagesize; - u32 rootdev; -}; - -/* it is allowed to have multiple ATAG_MEM nodes */ -#define ATAG_MEM 0x54410002 -/* ATAG_MEM uses tag_mem_range */ - -/* command line: \0 terminated string */ -#define ATAG_CMDLINE 0x54410003 - -struct tag_cmdline { - char cmdline[1]; /* this is the minimum size */ -}; - -/* Ramdisk image (may be compressed) */ -#define ATAG_RDIMG 0x54410004 -/* ATAG_RDIMG uses tag_mem_range */ - -/* Information about various clocks present in the system */ -#define ATAG_CLOCK 0x54410005 - -struct tag_clock { - u32 clock_id; /* Which clock are we talking about? */ - u32 clock_flags; /* Special features */ - u64 clock_hz; /* Clock speed in Hz */ -}; - -/* The clock types we know about */ -#define CLOCK_BOOTCPU 0 - -/* Memory reserved for the system (e.g. the bootloader) */ -#define ATAG_RSVD_MEM 0x54410006 -/* ATAG_RSVD_MEM uses tag_mem_range */ - -/* Ethernet information */ - -#define ATAG_ETHERNET 0x54410007 - -struct tag_ethernet { - u8 mac_index; - u8 mii_phy_addr; - u8 hw_address[6]; -}; - -#define ETH_INVALID_PHY 0xff - -/* board information */ -#define ATAG_BOARDINFO 0x54410008 - -struct tag_boardinfo { - u32 board_number; -}; - -struct tag { - struct tag_header hdr; - union { - struct tag_core core; - struct tag_mem_range mem_range; - struct tag_cmdline cmdline; - struct tag_clock clock; - struct tag_ethernet ethernet; - struct tag_boardinfo boardinfo; - } u; -}; - -struct tagtable { - u32 tag; - int (*parse)(struct tag *); -}; - -#define __tag __used __attribute__((__section__(".taglist.init"))) -#define __tagtable(tag, fn) \ - static struct tagtable __tagtable_##fn __tag = { tag, fn } - -#define tag_member_present(tag,member) \ - ((unsigned long)(&((struct tag *)0L)->member + 1) \ - <= (tag)->hdr.size * 4) - -#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)) -#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) - -#define for_each_tag(t,base) \ - for (t = base; t->hdr.size; t = tag_next(t)) - -extern struct tag *bootloader_tags; - -extern resource_size_t fbmem_start; -extern resource_size_t fbmem_size; -extern u32 board_number; - -void setup_processor(void); - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_AVR32_SETUP_H__ */ diff --git a/arch/avr32/include/asm/shmparam.h b/arch/avr32/include/asm/shmparam.h deleted file mode 100644 index 3681266c77f7..000000000000 --- a/arch/avr32/include/asm/shmparam.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_AVR32_SHMPARAM_H -#define __ASM_AVR32_SHMPARAM_H - -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ - -#endif /* __ASM_AVR32_SHMPARAM_H */ diff --git a/arch/avr32/include/asm/signal.h b/arch/avr32/include/asm/signal.h deleted file mode 100644 index d875eb6a3f3c..000000000000 --- a/arch/avr32/include/asm/signal.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_SIGNAL_H -#define __ASM_AVR32_SIGNAL_H - -#include <uapi/asm/signal.h> - -/* Most things should be clean enough to redefine this at will, if care - is taken to make libc match. */ - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#define __ARCH_HAS_SA_RESTORER - -#include <asm/sigcontext.h> -#undef __HAVE_ARCH_SIG_BITOPS - -#endif diff --git a/arch/avr32/include/asm/string.h b/arch/avr32/include/asm/string.h deleted file mode 100644 index c91a623cd585..000000000000 --- a/arch/avr32/include/asm/string.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_STRING_H -#define __ASM_AVR32_STRING_H - -#define __HAVE_ARCH_MEMSET -extern void *memset(void *b, int c, size_t len); - -#define __HAVE_ARCH_MEMCPY -extern void *memcpy(void *to, const void *from, size_t len); - -#endif /* __ASM_AVR32_STRING_H */ diff --git a/arch/avr32/include/asm/switch_to.h b/arch/avr32/include/asm/switch_to.h deleted file mode 100644 index 6f00581c3d4f..000000000000 --- a/arch/avr32/include/asm/switch_to.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_SWITCH_TO_H -#define __ASM_AVR32_SWITCH_TO_H - -/* - * Help PathFinder and other Nexus-compliant debuggers keep track of - * the current PID by emitting an Ownership Trace Message each time we - * switch task. - */ -#ifdef CONFIG_OWNERSHIP_TRACE -#include <asm/ocd.h> -#define ocd_switch(prev, next) \ - do { \ - ocd_write(PID, prev->pid); \ - ocd_write(PID, next->pid); \ - } while(0) -#else -#define ocd_switch(prev, next) -#endif - -/* - * switch_to(prev, next, last) should switch from task `prev' to task - * `next'. `prev' will never be the same as `next'. - * - * We just delegate everything to the __switch_to assembly function, - * which is implemented in arch/avr32/kernel/switch_to.S - * - * mb() tells GCC not to cache `current' across this call. - */ -struct cpu_context; -struct task_struct; -extern struct task_struct *__switch_to(struct task_struct *, - struct cpu_context *, - struct cpu_context *); -#define switch_to(prev, next, last) \ - do { \ - ocd_switch(prev, next); \ - last = __switch_to(prev, &prev->thread.cpu_context + 1, \ - &next->thread.cpu_context); \ - } while (0) - - -#endif /* __ASM_AVR32_SWITCH_TO_H */ diff --git a/arch/avr32/include/asm/syscalls.h b/arch/avr32/include/asm/syscalls.h deleted file mode 100644 index 244f2acab546..000000000000 --- a/arch/avr32/include/asm/syscalls.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * syscalls.h - Linux syscall interfaces (arch-specific) - * - * Copyright (c) 2008 Jaswinder Singh - * - * This file is released under the GPLv2. - * See the file COPYING for more details. - */ - -#ifndef _ASM_AVR32_SYSCALLS_H -#define _ASM_AVR32_SYSCALLS_H - -#include <linux/compiler.h> -#include <linux/linkage.h> -#include <linux/types.h> -#include <linux/signal.h> - -/* mm/cache.c */ -asmlinkage int sys_cacheflush(int, void __user *, size_t); - -#endif /* _ASM_AVR32_SYSCALLS_H */ diff --git a/arch/avr32/include/asm/sysreg.h b/arch/avr32/include/asm/sysreg.h deleted file mode 100644 index d4e0950170ca..000000000000 --- a/arch/avr32/include/asm/sysreg.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * AVR32 System Registers - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_SYSREG_H -#define __ASM_AVR32_SYSREG_H - -/* sysreg register offsets */ -#define SYSREG_SR 0x0000 -#define SYSREG_EVBA 0x0004 -#define SYSREG_ACBA 0x0008 -#define SYSREG_CPUCR 0x000c -#define SYSREG_ECR 0x0010 -#define SYSREG_RSR_SUP 0x0014 -#define SYSREG_RSR_INT0 0x0018 -#define SYSREG_RSR_INT1 0x001c -#define SYSREG_RSR_INT2 0x0020 -#define SYSREG_RSR_INT3 0x0024 -#define SYSREG_RSR_EX 0x0028 -#define SYSREG_RSR_NMI 0x002c -#define SYSREG_RSR_DBG 0x0030 -#define SYSREG_RAR_SUP 0x0034 -#define SYSREG_RAR_INT0 0x0038 -#define SYSREG_RAR_INT1 0x003c -#define SYSREG_RAR_INT2 0x0040 -#define SYSREG_RAR_INT3 0x0044 -#define SYSREG_RAR_EX 0x0048 -#define SYSREG_RAR_NMI 0x004c -#define SYSREG_RAR_DBG 0x0050 -#define SYSREG_JECR 0x0054 -#define SYSREG_JOSP 0x0058 -#define SYSREG_JAVA_LV0 0x005c -#define SYSREG_JAVA_LV1 0x0060 -#define SYSREG_JAVA_LV2 0x0064 -#define SYSREG_JAVA_LV3 0x0068 -#define SYSREG_JAVA_LV4 0x006c -#define SYSREG_JAVA_LV5 0x0070 -#define SYSREG_JAVA_LV6 0x0074 -#define SYSREG_JAVA_LV7 0x0078 -#define SYSREG_JTBA 0x007c -#define SYSREG_JBCR 0x0080 -#define SYSREG_CONFIG0 0x0100 -#define SYSREG_CONFIG1 0x0104 -#define SYSREG_COUNT 0x0108 -#define SYSREG_COMPARE 0x010c -#define SYSREG_TLBEHI 0x0110 -#define SYSREG_TLBELO 0x0114 -#define SYSREG_PTBR 0x0118 -#define SYSREG_TLBEAR 0x011c -#define SYSREG_MMUCR 0x0120 -#define SYSREG_TLBARLO 0x0124 -#define SYSREG_TLBARHI 0x0128 -#define SYSREG_PCCNT 0x012c -#define SYSREG_PCNT0 0x0130 -#define SYSREG_PCNT1 0x0134 -#define SYSREG_PCCR 0x0138 -#define SYSREG_BEAR 0x013c -#define SYSREG_SABAL 0x0300 -#define SYSREG_SABAH 0x0304 -#define SYSREG_SABD 0x0308 - -/* Bitfields in SR */ -#define SYSREG_SR_C_OFFSET 0 -#define SYSREG_SR_C_SIZE 1 -#define SYSREG_Z_OFFSET 1 -#define SYSREG_Z_SIZE 1 -#define SYSREG_SR_N_OFFSET 2 -#define SYSREG_SR_N_SIZE 1 -#define SYSREG_SR_V_OFFSET 3 -#define SYSREG_SR_V_SIZE 1 -#define SYSREG_Q_OFFSET 4 -#define SYSREG_Q_SIZE 1 -#define SYSREG_L_OFFSET 5 -#define SYSREG_L_SIZE 1 -#define SYSREG_T_OFFSET 14 -#define SYSREG_T_SIZE 1 -#define SYSREG_SR_R_OFFSET 15 -#define SYSREG_SR_R_SIZE 1 -#define SYSREG_GM_OFFSET 16 -#define SYSREG_GM_SIZE 1 -#define SYSREG_I0M_OFFSET 17 -#define SYSREG_I0M_SIZE 1 -#define SYSREG_I1M_OFFSET 18 -#define SYSREG_I1M_SIZE 1 -#define SYSREG_I2M_OFFSET 19 -#define SYSREG_I2M_SIZE 1 -#define SYSREG_I3M_OFFSET 20 -#define SYSREG_I3M_SIZE 1 -#define SYSREG_EM_OFFSET 21 -#define SYSREG_EM_SIZE 1 -#define SYSREG_MODE_OFFSET 22 -#define SYSREG_MODE_SIZE 3 -#define SYSREG_M0_OFFSET 22 -#define SYSREG_M0_SIZE 1 -#define SYSREG_M1_OFFSET 23 -#define SYSREG_M1_SIZE 1 -#define SYSREG_M2_OFFSET 24 -#define SYSREG_M2_SIZE 1 -#define SYSREG_SR_D_OFFSET 26 -#define SYSREG_SR_D_SIZE 1 -#define SYSREG_DM_OFFSET 27 -#define SYSREG_DM_SIZE 1 -#define SYSREG_SR_J_OFFSET 28 -#define SYSREG_SR_J_SIZE 1 -#define SYSREG_H_OFFSET 29 -#define SYSREG_H_SIZE 1 - -/* Bitfields in CPUCR */ -#define SYSREG_BI_OFFSET 0 -#define SYSREG_BI_SIZE 1 -#define SYSREG_BE_OFFSET 1 -#define SYSREG_BE_SIZE 1 -#define SYSREG_FE_OFFSET 2 -#define SYSREG_FE_SIZE 1 -#define SYSREG_RE_OFFSET 3 -#define SYSREG_RE_SIZE 1 -#define SYSREG_IBE_OFFSET 4 -#define SYSREG_IBE_SIZE 1 -#define SYSREG_IEE_OFFSET 5 -#define SYSREG_IEE_SIZE 1 - -/* Bitfields in CONFIG0 */ -#define SYSREG_CONFIG0_R_OFFSET 0 -#define SYSREG_CONFIG0_R_SIZE 1 -#define SYSREG_CONFIG0_D_OFFSET 1 -#define SYSREG_CONFIG0_D_SIZE 1 -#define SYSREG_CONFIG0_S_OFFSET 2 -#define SYSREG_CONFIG0_S_SIZE 1 -#define SYSREG_CONFIG0_O_OFFSET 3 -#define SYSREG_CONFIG0_O_SIZE 1 -#define SYSREG_CONFIG0_P_OFFSET 4 -#define SYSREG_CONFIG0_P_SIZE 1 -#define SYSREG_CONFIG0_J_OFFSET 5 -#define SYSREG_CONFIG0_J_SIZE 1 -#define SYSREG_CONFIG0_F_OFFSET 6 -#define SYSREG_CONFIG0_F_SIZE 1 -#define SYSREG_MMUT_OFFSET 7 -#define SYSREG_MMUT_SIZE 3 -#define SYSREG_AR_OFFSET 10 -#define SYSREG_AR_SIZE 3 -#define SYSREG_AT_OFFSET 13 -#define SYSREG_AT_SIZE 3 -#define SYSREG_PROCESSORREVISION_OFFSET 16 -#define SYSREG_PROCESSORREVISION_SIZE 8 -#define SYSREG_PROCESSORID_OFFSET 24 -#define SYSREG_PROCESSORID_SIZE 8 - -/* Bitfields in CONFIG1 */ -#define SYSREG_DASS_OFFSET 0 -#define SYSREG_DASS_SIZE 3 -#define SYSREG_DLSZ_OFFSET 3 -#define SYSREG_DLSZ_SIZE 3 -#define SYSREG_DSET_OFFSET 6 -#define SYSREG_DSET_SIZE 4 -#define SYSREG_IASS_OFFSET 10 -#define SYSREG_IASS_SIZE 3 -#define SYSREG_ILSZ_OFFSET 13 -#define SYSREG_ILSZ_SIZE 3 -#define SYSREG_ISET_OFFSET 16 -#define SYSREG_ISET_SIZE 4 -#define SYSREG_DMMUSZ_OFFSET 20 -#define SYSREG_DMMUSZ_SIZE 6 -#define SYSREG_IMMUSZ_OFFSET 26 -#define SYSREG_IMMUSZ_SIZE 6 - -/* Bitfields in TLBEHI */ -#define SYSREG_ASID_OFFSET 0 -#define SYSREG_ASID_SIZE 8 -#define SYSREG_TLBEHI_I_OFFSET 8 -#define SYSREG_TLBEHI_I_SIZE 1 -#define SYSREG_TLBEHI_V_OFFSET 9 -#define SYSREG_TLBEHI_V_SIZE 1 -#define SYSREG_VPN_OFFSET 10 -#define SYSREG_VPN_SIZE 22 - -/* Bitfields in TLBELO */ -#define SYSREG_W_OFFSET 0 -#define SYSREG_W_SIZE 1 -#define SYSREG_TLBELO_D_OFFSET 1 -#define SYSREG_TLBELO_D_SIZE 1 -#define SYSREG_SZ_OFFSET 2 -#define SYSREG_SZ_SIZE 2 -#define SYSREG_AP_OFFSET 4 -#define SYSREG_AP_SIZE 3 -#define SYSREG_B_OFFSET 7 -#define SYSREG_B_SIZE 1 -#define SYSREG_G_OFFSET 8 -#define SYSREG_G_SIZE 1 -#define SYSREG_TLBELO_C_OFFSET 9 -#define SYSREG_TLBELO_C_SIZE 1 -#define SYSREG_PFN_OFFSET 10 -#define SYSREG_PFN_SIZE 22 - -/* Bitfields in MMUCR */ -#define SYSREG_E_OFFSET 0 -#define SYSREG_E_SIZE 1 -#define SYSREG_M_OFFSET 1 -#define SYSREG_M_SIZE 1 -#define SYSREG_MMUCR_I_OFFSET 2 -#define SYSREG_MMUCR_I_SIZE 1 -#define SYSREG_MMUCR_N_OFFSET 3 -#define SYSREG_MMUCR_N_SIZE 1 -#define SYSREG_MMUCR_S_OFFSET 4 -#define SYSREG_MMUCR_S_SIZE 1 -#define SYSREG_DLA_OFFSET 8 -#define SYSREG_DLA_SIZE 6 -#define SYSREG_DRP_OFFSET 14 -#define SYSREG_DRP_SIZE 6 -#define SYSREG_ILA_OFFSET 20 -#define SYSREG_ILA_SIZE 6 -#define SYSREG_IRP_OFFSET 26 -#define SYSREG_IRP_SIZE 6 - -/* Bitfields in PCCR */ -#define SYSREG_PCCR_E_OFFSET 0 -#define SYSREG_PCCR_E_SIZE 1 -#define SYSREG_PCCR_R_OFFSET 1 -#define SYSREG_PCCR_R_SIZE 1 -#define SYSREG_PCCR_C_OFFSET 2 -#define SYSREG_PCCR_C_SIZE 1 -#define SYSREG_PCCR_S_OFFSET 3 -#define SYSREG_PCCR_S_SIZE 1 -#define SYSREG_IEC_OFFSET 4 -#define SYSREG_IEC_SIZE 1 -#define SYSREG_IE0_OFFSET 5 -#define SYSREG_IE0_SIZE 1 -#define SYSREG_IE1_OFFSET 6 -#define SYSREG_IE1_SIZE 1 -#define SYSREG_FC_OFFSET 8 -#define SYSREG_FC_SIZE 1 -#define SYSREG_F0_OFFSET 9 -#define SYSREG_F0_SIZE 1 -#define SYSREG_F1_OFFSET 10 -#define SYSREG_F1_SIZE 1 -#define SYSREG_CONF0_OFFSET 12 -#define SYSREG_CONF0_SIZE 6 -#define SYSREG_CONF1_OFFSET 18 -#define SYSREG_CONF1_SIZE 6 - -/* Constants for ECR */ -#define ECR_UNRECOVERABLE 0 -#define ECR_TLB_MULTIPLE 1 -#define ECR_BUS_ERROR_WRITE 2 -#define ECR_BUS_ERROR_READ 3 -#define ECR_NMI 4 -#define ECR_ADDR_ALIGN_X 5 -#define ECR_PROTECTION_X 6 -#define ECR_DEBUG 7 -#define ECR_ILLEGAL_OPCODE 8 -#define ECR_UNIMPL_INSTRUCTION 9 -#define ECR_PRIVILEGE_VIOLATION 10 -#define ECR_FPE 11 -#define ECR_COPROC_ABSENT 12 -#define ECR_ADDR_ALIGN_R 13 -#define ECR_ADDR_ALIGN_W 14 -#define ECR_PROTECTION_R 15 -#define ECR_PROTECTION_W 16 -#define ECR_DTLB_MODIFIED 17 -#define ECR_TLB_MISS_X 20 -#define ECR_TLB_MISS_R 24 -#define ECR_TLB_MISS_W 28 - -/* Bit manipulation macros */ -#define SYSREG_BIT(name) \ - (1 << SYSREG_##name##_OFFSET) -#define SYSREG_BF(name,value) \ - (((value) & ((1 << SYSREG_##name##_SIZE) - 1)) \ - << SYSREG_##name##_OFFSET) -#define SYSREG_BFEXT(name,value)\ - (((value) >> SYSREG_##name##_OFFSET) \ - & ((1 << SYSREG_##name##_SIZE) - 1)) -#define SYSREG_BFINS(name,value,old) \ - (((old) & ~(((1 << SYSREG_##name##_SIZE) - 1) \ - << SYSREG_##name##_OFFSET)) \ - | SYSREG_BF(name,value)) - -/* Register access macros */ -#ifdef __CHECKER__ -extern unsigned long __builtin_mfsr(unsigned long reg); -extern void __builtin_mtsr(unsigned long reg, unsigned long value); -#endif - -#define sysreg_read(reg) __builtin_mfsr(SYSREG_##reg) -#define sysreg_write(reg, value) __builtin_mtsr(SYSREG_##reg, value) - -#endif /* __ASM_AVR32_SYSREG_H */ diff --git a/arch/avr32/include/asm/termios.h b/arch/avr32/include/asm/termios.h deleted file mode 100644 index 9d594376dbd6..000000000000 --- a/arch/avr32/include/asm/termios.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_TERMIOS_H -#define __ASM_AVR32_TERMIOS_H - -#include <uapi/asm/termios.h> - -/* intr=^C quit=^\ erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 -*/ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" - -#include <asm-generic/termios-base.h> - -#endif /* __ASM_AVR32_TERMIOS_H */ diff --git a/arch/avr32/include/asm/thread_info.h b/arch/avr32/include/asm/thread_info.h deleted file mode 100644 index d4d3079541ea..000000000000 --- a/arch/avr32/include/asm/thread_info.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_THREAD_INFO_H -#define __ASM_AVR32_THREAD_INFO_H - -#include <asm/page.h> - -#define THREAD_SIZE_ORDER 1 -#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) - -#ifndef __ASSEMBLY__ -#include <asm/types.h> - -struct task_struct; - -struct thread_info { - struct task_struct *task; /* main task structure */ - unsigned long flags; /* low level flags */ - __u32 cpu; - __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ - __u32 rar_saved; /* return address... */ - __u32 rsr_saved; /* ...and status register - saved by debug handler - when setting up - trampoline */ - __u8 supervisor_stack[0]; -}; - -#define INIT_THREAD_INFO(tsk) \ -{ \ - .task = &tsk, \ - .flags = 0, \ - .cpu = 0, \ - .preempt_count = INIT_PREEMPT_COUNT, \ -} - -#define init_thread_info (init_thread_union.thread_info) -#define init_stack (init_thread_union.stack) - -/* - * Get the thread information struct from C. - * We do the usual trick and use the lower end of the stack for this - */ -static inline struct thread_info *current_thread_info(void) -{ - unsigned long addr = ~(THREAD_SIZE - 1); - - asm("and %0, sp" : "=r"(addr) : "0"(addr)); - return (struct thread_info *)addr; -} - -#define get_thread_info(ti) get_task_struct((ti)->task) -#define put_thread_info(ti) put_task_struct((ti)->task) - -#endif /* !__ASSEMBLY__ */ - -/* - * Thread information flags - * - these are process state flags that various assembly files may need to access - * - pending work-to-be-done flags are in LSW - * - other flags in MSW - */ -#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_SIGPENDING 1 /* signal pending */ -#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ -#define TIF_BREAKPOINT 4 /* enter monitor mode on return */ -#define TIF_SINGLE_STEP 5 /* single step in progress */ -#define TIF_MEMDIE 6 /* is terminating due to OOM killer */ -#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal */ -#define TIF_CPU_GOING_TO_SLEEP 8 /* CPU is entering sleep 0 mode */ -#define TIF_NOTIFY_RESUME 9 /* callback before returning to user */ -#define TIF_DEBUG 30 /* debugging enabled */ -#define TIF_USERSPACE 31 /* true if FS sets userspace */ - -#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) -#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) -#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_BREAKPOINT (1 << TIF_BREAKPOINT) -#define _TIF_SINGLE_STEP (1 << TIF_SINGLE_STEP) -#define _TIF_MEMDIE (1 << TIF_MEMDIE) -#define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP) -#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) - -/* Note: The masks below must never span more than 16 bits! */ - -/* work to do on interrupt/exception return */ -#define _TIF_WORK_MASK \ - (_TIF_SIGPENDING \ - | _TIF_NOTIFY_RESUME \ - | _TIF_NEED_RESCHED \ - | _TIF_BREAKPOINT) - -/* work to do on any return to userspace */ -#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE) -/* work to do on return from debug mode */ -#define _TIF_DBGWORK_MASK (_TIF_WORK_MASK & ~_TIF_BREAKPOINT) - -#endif /* __ASM_AVR32_THREAD_INFO_H */ diff --git a/arch/avr32/include/asm/timex.h b/arch/avr32/include/asm/timex.h deleted file mode 100644 index 187dcf38b210..000000000000 --- a/arch/avr32/include/asm/timex.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_TIMEX_H -#define __ASM_AVR32_TIMEX_H - -/* - * This is the frequency of the timer used for Linux's timer interrupt. - * The value should be defined as accurate as possible or under certain - * circumstances Linux timekeeping might become inaccurate or fail. - * - * For many system the exact clockrate of the timer isn't known but due to - * the way this value is used we can get away with a wrong value as long - * as this value is: - * - * - a multiple of HZ - * - a divisor of the actual rate - * - * 500000 is a good such cheat value. - * - * The obscure number 1193182 is the same as used by the original i8254 - * time in legacy PC hardware; the chip is never found in AVR32 systems. - */ -#define CLOCK_TICK_RATE 500000 /* Underlying HZ */ - -typedef unsigned long cycles_t; - -static inline cycles_t get_cycles (void) -{ - return 0; -} - -#define ARCH_HAS_READ_CURRENT_TIMER - -#endif /* __ASM_AVR32_TIMEX_H */ diff --git a/arch/avr32/include/asm/tlb.h b/arch/avr32/include/asm/tlb.h deleted file mode 100644 index 5c55f9ce7c7d..000000000000 --- a/arch/avr32/include/asm/tlb.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_TLB_H -#define __ASM_AVR32_TLB_H - -#define tlb_start_vma(tlb, vma) \ - flush_cache_range(vma, vma->vm_start, vma->vm_end) - -#define tlb_end_vma(tlb, vma) \ - flush_tlb_range(vma, vma->vm_start, vma->vm_end) - -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while(0) - -/* - * Flush whole TLB for MM - */ -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) - -#include <asm-generic/tlb.h> - -/* - * For debugging purposes - */ -extern void show_dtlb_entry(unsigned int index); -extern void dump_dtlb(void); - -#endif /* __ASM_AVR32_TLB_H */ diff --git a/arch/avr32/include/asm/tlbflush.h b/arch/avr32/include/asm/tlbflush.h deleted file mode 100644 index bf90a786f6be..000000000000 --- a/arch/avr32/include/asm/tlbflush.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_TLBFLUSH_H -#define __ASM_AVR32_TLBFLUSH_H - -#include <asm/mmu.h> - -/* - * TLB flushing: - * - * - flush_tlb() flushes the current mm struct TLBs - * - flush_tlb_all() flushes all processes' TLB entries - * - flush_tlb_mm(mm) flushes the specified mm context TLBs - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(vma, start, end) flushes a range of pages - * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages - */ -extern void flush_tlb(void); -extern void flush_tlb_all(void); -extern void flush_tlb_mm(struct mm_struct *mm); -extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); - -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); - -#endif /* __ASM_AVR32_TLBFLUSH_H */ diff --git a/arch/avr32/include/asm/traps.h b/arch/avr32/include/asm/traps.h deleted file mode 100644 index 6a8fb944f414..000000000000 --- a/arch/avr32/include/asm/traps.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_TRAPS_H -#define __ASM_AVR32_TRAPS_H - -#include <linux/list.h> - -struct undef_hook { - struct list_head node; - u32 insn_mask; - u32 insn_val; - int (*fn)(struct pt_regs *regs, u32 insn); -}; - -void register_undef_hook(struct undef_hook *hook); -void unregister_undef_hook(struct undef_hook *hook); - -#endif /* __ASM_AVR32_TRAPS_H */ diff --git a/arch/avr32/include/asm/types.h b/arch/avr32/include/asm/types.h deleted file mode 100644 index 59324058069c..000000000000 --- a/arch/avr32/include/asm/types.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_TYPES_H -#define __ASM_AVR32_TYPES_H - -#include <uapi/asm/types.h> - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ - -#define BITS_PER_LONG 32 - -#endif /* __ASM_AVR32_TYPES_H */ diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h deleted file mode 100644 index b1ec1fa06463..000000000000 --- a/arch/avr32/include/asm/uaccess.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_UACCESS_H -#define __ASM_AVR32_UACCESS_H - -#include <linux/errno.h> -#include <linux/sched.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -typedef struct { - unsigned int is_user_space; -} mm_segment_t; - -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons (Data Segment Register?), these macros are misnamed. - */ -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -#define segment_eq(a, b) ((a).is_user_space == (b).is_user_space) - -#define USER_ADDR_LIMIT 0x80000000 - -#define KERNEL_DS MAKE_MM_SEG(0) -#define USER_DS MAKE_MM_SEG(1) - -#define get_ds() (KERNEL_DS) - -static inline mm_segment_t get_fs(void) -{ - return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE)); -} - -static inline void set_fs(mm_segment_t s) -{ - if (s.is_user_space) - set_thread_flag(TIF_USERSPACE); - else - clear_thread_flag(TIF_USERSPACE); -} - -/* - * Test whether a block of memory is a valid user space address. - * Returns 0 if the range is valid, nonzero otherwise. - * - * We do the following checks: - * 1. Is the access from kernel space? - * 2. Does (addr + size) set the carry bit? - * 3. Is (addr + size) a negative number (i.e. >= 0x80000000)? - * - * If yes on the first check, access is granted. - * If no on any of the others, access is denied. - */ -#define __range_ok(addr, size) \ - (test_thread_flag(TIF_USERSPACE) \ - && (((unsigned long)(addr) >= 0x80000000) \ - || ((unsigned long)(size) > 0x80000000) \ - || (((unsigned long)(addr) + (unsigned long)(size)) > 0x80000000))) - -#define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0)) - -/* Generic arbitrary sized copy. Return the number of bytes NOT copied */ -extern __kernel_size_t __copy_user(void *to, const void *from, - __kernel_size_t n); - -extern __kernel_size_t copy_to_user(void __user *to, const void *from, - __kernel_size_t n); -extern __kernel_size_t ___copy_from_user(void *to, const void __user *from, - __kernel_size_t n); - -static inline __kernel_size_t __copy_to_user(void __user *to, const void *from, - __kernel_size_t n) -{ - return __copy_user((void __force *)to, from, n); -} -static inline __kernel_size_t __copy_from_user(void *to, - const void __user *from, - __kernel_size_t n) -{ - return __copy_user(to, (const void __force *)from, n); -} -static inline __kernel_size_t copy_from_user(void *to, - const void __user *from, - __kernel_size_t n) -{ - size_t res = ___copy_from_user(to, from, n); - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; -} - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -/* - * put_user: - Write a simple value into user space. - * @x: Value to copy to user space. - * @ptr: Destination address, in user space. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * This macro copies a single simple value from kernel space to user - * space. It supports simple types like char and int, but not larger - * data types like structures or arrays. - * - * @ptr must have pointer-to-simple-variable type, and @x must be assignable - * to the result of dereferencing @ptr. - * - * Returns zero on success, or -EFAULT on error. - */ -#define put_user(x, ptr) \ - __put_user_check((x), (ptr), sizeof(*(ptr))) - -/* - * get_user: - Get a simple variable from user space. - * @x: Variable to store result. - * @ptr: Source address, in user space. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * This macro copies a single simple variable from user space to kernel - * space. It supports simple types like char and int, but not larger - * data types like structures or arrays. - * - * @ptr must have pointer-to-simple-variable type, and the result of - * dereferencing @ptr must be assignable to @x without a cast. - * - * Returns zero on success, or -EFAULT on error. - * On error, the variable @x is set to zero. - */ -#define get_user(x, ptr) \ - __get_user_check((x), (ptr), sizeof(*(ptr))) - -/* - * __put_user: - Write a simple value into user space, with less checking. - * @x: Value to copy to user space. - * @ptr: Destination address, in user space. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * This macro copies a single simple value from kernel space to user - * space. It supports simple types like char and int, but not larger - * data types like structures or arrays. - * - * @ptr must have pointer-to-simple-variable type, and @x must be assignable - * to the result of dereferencing @ptr. - * - * Caller must check the pointer with access_ok() before calling this - * function. - * - * Returns zero on success, or -EFAULT on error. - */ -#define __put_user(x, ptr) \ - __put_user_nocheck((x), (ptr), sizeof(*(ptr))) - -/* - * __get_user: - Get a simple variable from user space, with less checking. - * @x: Variable to store result. - * @ptr: Source address, in user space. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * This macro copies a single simple variable from user space to kernel - * space. It supports simple types like char and int, but not larger - * data types like structures or arrays. - * - * @ptr must have pointer-to-simple-variable type, and the result of - * dereferencing @ptr must be assignable to @x without a cast. - * - * Caller must check the pointer with access_ok() before calling this - * function. - * - * Returns zero on success, or -EFAULT on error. - * On error, the variable @x is set to zero. - */ -#define __get_user(x, ptr) \ - __get_user_nocheck((x), (ptr), sizeof(*(ptr))) - -extern int __get_user_bad(void); -extern int __put_user_bad(void); - -#define __get_user_nocheck(x, ptr, size) \ -({ \ - unsigned long __gu_val = 0; \ - int __gu_err = 0; \ - \ - switch (size) { \ - case 1: __get_user_asm("ub", __gu_val, ptr, __gu_err); break; \ - case 2: __get_user_asm("uh", __gu_val, ptr, __gu_err); break; \ - case 4: __get_user_asm("w", __gu_val, ptr, __gu_err); break; \ - default: __gu_err = __get_user_bad(); break; \ - } \ - \ - x = (__force typeof(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_check(x, ptr, size) \ -({ \ - unsigned long __gu_val = 0; \ - const typeof(*(ptr)) __user * __gu_addr = (ptr); \ - int __gu_err = 0; \ - \ - if (access_ok(VERIFY_READ, __gu_addr, size)) { \ - switch (size) { \ - case 1: \ - __get_user_asm("ub", __gu_val, __gu_addr, \ - __gu_err); \ - break; \ - case 2: \ - __get_user_asm("uh", __gu_val, __gu_addr, \ - __gu_err); \ - break; \ - case 4: \ - __get_user_asm("w", __gu_val, __gu_addr, \ - __gu_err); \ - break; \ - default: \ - __gu_err = __get_user_bad(); \ - break; \ - } \ - } else { \ - __gu_err = -EFAULT; \ - } \ - x = (__force typeof(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_asm(suffix, __gu_val, ptr, __gu_err) \ - asm volatile( \ - "1: ld." suffix " %1, %3 \n" \ - "2: \n" \ - " .subsection 1 \n" \ - "3: mov %0, %4 \n" \ - " rjmp 2b \n" \ - " .subsection 0 \n" \ - " .section __ex_table, \"a\" \n" \ - " .long 1b, 3b \n" \ - " .previous \n" \ - : "=r"(__gu_err), "=r"(__gu_val) \ - : "0"(__gu_err), "m"(*(ptr)), "i"(-EFAULT)) - -#define __put_user_nocheck(x, ptr, size) \ -({ \ - typeof(*(ptr)) __pu_val; \ - int __pu_err = 0; \ - \ - __pu_val = (x); \ - switch (size) { \ - case 1: __put_user_asm("b", ptr, __pu_val, __pu_err); break; \ - case 2: __put_user_asm("h", ptr, __pu_val, __pu_err); break; \ - case 4: __put_user_asm("w", ptr, __pu_val, __pu_err); break; \ - case 8: __put_user_asm("d", ptr, __pu_val, __pu_err); break; \ - default: __pu_err = __put_user_bad(); break; \ - } \ - __pu_err; \ -}) - -#define __put_user_check(x, ptr, size) \ -({ \ - typeof(*(ptr)) __pu_val; \ - typeof(*(ptr)) __user *__pu_addr = (ptr); \ - int __pu_err = 0; \ - \ - __pu_val = (x); \ - if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \ - switch (size) { \ - case 1: \ - __put_user_asm("b", __pu_addr, __pu_val, \ - __pu_err); \ - break; \ - case 2: \ - __put_user_asm("h", __pu_addr, __pu_val, \ - __pu_err); \ - break; \ - case 4: \ - __put_user_asm("w", __pu_addr, __pu_val, \ - __pu_err); \ - break; \ - case 8: \ - __put_user_asm("d", __pu_addr, __pu_val, \ - __pu_err); \ - break; \ - default: \ - __pu_err = __put_user_bad(); \ - break; \ - } \ - } else { \ - __pu_err = -EFAULT; \ - } \ - __pu_err; \ -}) - -#define __put_user_asm(suffix, ptr, __pu_val, __gu_err) \ - asm volatile( \ - "1: st." suffix " %1, %3 \n" \ - "2: \n" \ - " .subsection 1 \n" \ - "3: mov %0, %4 \n" \ - " rjmp 2b \n" \ - " .subsection 0 \n" \ - " .section __ex_table, \"a\" \n" \ - " .long 1b, 3b \n" \ - " .previous \n" \ - : "=r"(__gu_err), "=m"(*(ptr)) \ - : "0"(__gu_err), "r"(__pu_val), "i"(-EFAULT)) - -extern __kernel_size_t clear_user(void __user *addr, __kernel_size_t size); -extern __kernel_size_t __clear_user(void __user *addr, __kernel_size_t size); - -extern long strncpy_from_user(char *dst, const char __user *src, long count); -extern long __strncpy_from_user(char *dst, const char __user *src, long count); - -extern long strnlen_user(const char __user *__s, long __n); -extern long __strnlen_user(const char __user *__s, long __n); - -#define strlen_user(s) strnlen_user(s, ~0UL >> 1) - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -#endif /* __ASM_AVR32_UACCESS_H */ diff --git a/arch/avr32/include/asm/ucontext.h b/arch/avr32/include/asm/ucontext.h deleted file mode 100644 index ac7259c2a799..000000000000 --- a/arch/avr32/include/asm/ucontext.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ASM_AVR32_UCONTEXT_H -#define __ASM_AVR32_UCONTEXT_H - -struct ucontext { - unsigned long uc_flags; - struct ucontext * uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; -}; - -#endif /* __ASM_AVR32_UCONTEXT_H */ diff --git a/arch/avr32/include/asm/unaligned.h b/arch/avr32/include/asm/unaligned.h deleted file mode 100644 index 041877290470..000000000000 --- a/arch/avr32/include/asm/unaligned.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _ASM_AVR32_UNALIGNED_H -#define _ASM_AVR32_UNALIGNED_H - -/* - * AVR32 can handle some unaligned accesses, depending on the - * implementation. The AVR32 AP implementation can handle unaligned - * words, but halfwords must be halfword-aligned, and doublewords must - * be word-aligned. - * - * However, swapped word loads must be word-aligned so we can't - * optimize word loads in general. - */ - -#include <linux/unaligned/be_struct.h> -#include <linux/unaligned/le_byteshift.h> -#include <linux/unaligned/generic.h> - -#define get_unaligned __get_unaligned_be -#define put_unaligned __put_unaligned_be - -#endif /* _ASM_AVR32_UNALIGNED_H */ diff --git a/arch/avr32/include/asm/unistd.h b/arch/avr32/include/asm/unistd.h deleted file mode 100644 index 2011bee3f252..000000000000 --- a/arch/avr32/include/asm/unistd.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ASM_AVR32_UNISTD_H -#define __ASM_AVR32_UNISTD_H - -#include <uapi/asm/unistd.h> - -#define NR_syscalls 321 - -/* Old stuff */ -#define __IGNORE_uselib -#define __IGNORE_mmap - -/* NUMA stuff */ -#define __IGNORE_mbind -#define __IGNORE_get_mempolicy -#define __IGNORE_set_mempolicy -#define __IGNORE_migrate_pages -#define __IGNORE_move_pages - -/* SMP stuff */ -#define __IGNORE_getcpu - -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_FORK -#define __ARCH_WANT_SYS_VFORK -#define __ARCH_WANT_SYS_CLONE - -#endif /* __ASM_AVR32_UNISTD_H */ diff --git a/arch/avr32/include/asm/user.h b/arch/avr32/include/asm/user.h deleted file mode 100644 index 7e9152f81f5e..000000000000 --- a/arch/avr32/include/asm/user.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - * - * Note: We may not need these definitions for AVR32, as we don't - * support a.out. - */ -#ifndef __ASM_AVR32_USER_H -#define __ASM_AVR32_USER_H - -#include <linux/types.h> -#include <asm/ptrace.h> -#include <asm/page.h> - -/* - * Core file format: The core file is written in such a way that gdb - * can understand it and provide useful information to the user (under - * linux we use the `trad-core' bfd). The file contents are as follows: - * - * upage: 1 page consisting of a user struct that tells gdb - * what is present in the file. Directly after this is a - * copy of the task_struct, which is currently not used by gdb, - * but it may come in handy at some point. All of the registers - * are stored as part of the upage. The upage should always be - * only one page long. - * data: The data segment follows next. We use current->end_text to - * current->brk to pick up all of the user variables, plus any memory - * that may have been sbrk'ed. No attempt is made to determine if a - * page is demand-zero or if a page is totally unused, we just cover - * the entire range. All of the addresses are rounded in such a way - * that an integral number of pages is written. - * stack: We need the stack information in order to get a meaningful - * backtrace. We need to write the data from usp to - * current->start_stack, so we round each of these in order to be able - * to write an integer number of pages. - */ - -struct user_fpu_struct { - /* We have no FPU (yet) */ -}; - -struct user { - struct pt_regs regs; /* entire machine state */ - size_t u_tsize; /* text size (pages) */ - size_t u_dsize; /* data size (pages) */ - size_t u_ssize; /* stack size (pages) */ - unsigned long start_code; /* text starting address */ - unsigned long start_data; /* data starting address */ - unsigned long start_stack; /* stack starting address */ - long int signal; /* signal causing core dump */ - unsigned long u_ar0; /* help gdb find registers */ - unsigned long magic; /* identifies a core file */ - char u_comm[32]; /* user command name */ -}; - -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_DATA_START_ADDR (u.start_data) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif /* __ASM_AVR32_USER_H */ diff --git a/arch/avr32/include/uapi/asm/Kbuild b/arch/avr32/include/uapi/asm/Kbuild deleted file mode 100644 index 08d8a3d76ea8..000000000000 --- a/arch/avr32/include/uapi/asm/Kbuild +++ /dev/null @@ -1,36 +0,0 @@ -# UAPI Header export list -include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += byteorder.h -header-y += cachectl.h -header-y += msgbuf.h -header-y += param.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h -generic-y += bitsperlong.h -generic-y += errno.h -generic-y += fcntl.h -generic-y += ioctl.h -generic-y += ioctls.h -generic-y += ipcbuf.h -generic-y += kvm_para.h -generic-y += mman.h -generic-y += param.h -generic-y += poll.h -generic-y += resource.h -generic-y += siginfo.h -generic-y += statfs.h diff --git a/arch/avr32/include/uapi/asm/auxvec.h b/arch/avr32/include/uapi/asm/auxvec.h deleted file mode 100644 index 4f02da3ffefa..000000000000 --- a/arch/avr32/include/uapi/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_AUXVEC_H -#define _UAPI__ASM_AVR32_AUXVEC_H - -#endif /* _UAPI__ASM_AVR32_AUXVEC_H */ diff --git a/arch/avr32/include/uapi/asm/byteorder.h b/arch/avr32/include/uapi/asm/byteorder.h deleted file mode 100644 index 71242f0d39c6..000000000000 --- a/arch/avr32/include/uapi/asm/byteorder.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * AVR32 endian-conversion functions. - */ -#ifndef _UAPI__ASM_AVR32_BYTEORDER_H -#define _UAPI__ASM_AVR32_BYTEORDER_H - -#include <linux/byteorder/big_endian.h> - -#endif /* _UAPI__ASM_AVR32_BYTEORDER_H */ diff --git a/arch/avr32/include/uapi/asm/cachectl.h b/arch/avr32/include/uapi/asm/cachectl.h deleted file mode 100644 index 573a9584dd57..000000000000 --- a/arch/avr32/include/uapi/asm/cachectl.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_CACHECTL_H -#define _UAPI__ASM_AVR32_CACHECTL_H - -/* - * Operations that can be performed through the cacheflush system call - */ - -/* Clean the data cache, then invalidate the icache */ -#define CACHE_IFLUSH 0 - -#endif /* _UAPI__ASM_AVR32_CACHECTL_H */ diff --git a/arch/avr32/include/uapi/asm/msgbuf.h b/arch/avr32/include/uapi/asm/msgbuf.h deleted file mode 100644 index 9eae6effad14..000000000000 --- a/arch/avr32/include/uapi/asm/msgbuf.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_MSGBUF_H -#define _UAPI__ASM_AVR32_MSGBUF_H - -/* - * The msqid64_ds structure for i386 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - unsigned long __unused1; - __kernel_time_t msg_rtime; /* last msgrcv time */ - unsigned long __unused2; - __kernel_time_t msg_ctime; /* last change time */ - unsigned long __unused3; - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused4; - unsigned long __unused5; -}; - -#endif /* _UAPI__ASM_AVR32_MSGBUF_H */ diff --git a/arch/avr32/include/uapi/asm/posix_types.h b/arch/avr32/include/uapi/asm/posix_types.h deleted file mode 100644 index 5b813a8abf09..000000000000 --- a/arch/avr32/include/uapi/asm/posix_types.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_POSIX_TYPES_H -#define _UAPI__ASM_AVR32_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned short __kernel_mode_t; -#define __kernel_mode_t __kernel_mode_t - -typedef unsigned short __kernel_ipc_pid_t; -#define __kernel_ipc_pid_t __kernel_ipc_pid_t - -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef int __kernel_ptrdiff_t; -#define __kernel_size_t __kernel_size_t - -typedef unsigned short __kernel_old_uid_t; -typedef unsigned short __kernel_old_gid_t; -#define __kernel_old_uid_t __kernel_old_uid_t - -typedef unsigned short __kernel_old_dev_t; -#define __kernel_old_dev_t __kernel_old_dev_t - -#include <asm-generic/posix_types.h> - -#endif /* _UAPI__ASM_AVR32_POSIX_TYPES_H */ diff --git a/arch/avr32/include/uapi/asm/ptrace.h b/arch/avr32/include/uapi/asm/ptrace.h deleted file mode 100644 index fe8c16275bc0..000000000000 --- a/arch/avr32/include/uapi/asm/ptrace.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_PTRACE_H -#define _UAPI__ASM_AVR32_PTRACE_H - -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 - -/* - * Status Register bits - */ -#define SR_H 0x20000000 -#define SR_J 0x10000000 -#define SR_DM 0x08000000 -#define SR_D 0x04000000 -#define MODE_NMI 0x01c00000 -#define MODE_EXCEPTION 0x01800000 -#define MODE_INT3 0x01400000 -#define MODE_INT2 0x01000000 -#define MODE_INT1 0x00c00000 -#define MODE_INT0 0x00800000 -#define MODE_SUPERVISOR 0x00400000 -#define MODE_USER 0x00000000 -#define MODE_MASK 0x01c00000 -#define SR_EM 0x00200000 -#define SR_I3M 0x00100000 -#define SR_I2M 0x00080000 -#define SR_I1M 0x00040000 -#define SR_I0M 0x00020000 -#define SR_GM 0x00010000 - -#define SR_H_BIT 29 -#define SR_J_BIT 28 -#define SR_DM_BIT 27 -#define SR_D_BIT 26 -#define MODE_SHIFT 22 -#define SR_EM_BIT 21 -#define SR_I3M_BIT 20 -#define SR_I2M_BIT 19 -#define SR_I1M_BIT 18 -#define SR_I0M_BIT 17 -#define SR_GM_BIT 16 - -/* The user-visible part */ -#define SR_L 0x00000020 -#define SR_Q 0x00000010 -#define SR_V 0x00000008 -#define SR_N 0x00000004 -#define SR_Z 0x00000002 -#define SR_C 0x00000001 - -#define SR_L_BIT 5 -#define SR_Q_BIT 4 -#define SR_V_BIT 3 -#define SR_N_BIT 2 -#define SR_Z_BIT 1 -#define SR_C_BIT 0 - -/* - * The order is defined by the stmts instruction. r0 is stored first, - * so it gets the highest address. - * - * Registers 0-12 are general-purpose registers (r12 is normally used for - * the function return value). - * Register 13 is the stack pointer - * Register 14 is the link register - * Register 15 is the program counter (retrieved from the RAR sysreg) - */ -#define FRAME_SIZE_FULL 72 -#define REG_R12_ORIG 68 -#define REG_R0 64 -#define REG_R1 60 -#define REG_R2 56 -#define REG_R3 52 -#define REG_R4 48 -#define REG_R5 44 -#define REG_R6 40 -#define REG_R7 36 -#define REG_R8 32 -#define REG_R9 28 -#define REG_R10 24 -#define REG_R11 20 -#define REG_R12 16 -#define REG_SP 12 -#define REG_LR 8 - -#define FRAME_SIZE_MIN 8 -#define REG_PC 4 -#define REG_SR 0 - -#ifndef __ASSEMBLY__ -struct pt_regs { - /* These are always saved */ - unsigned long sr; - unsigned long pc; - - /* These are sometimes saved */ - unsigned long lr; - unsigned long sp; - unsigned long r12; - unsigned long r11; - unsigned long r10; - unsigned long r9; - unsigned long r8; - unsigned long r7; - unsigned long r6; - unsigned long r5; - unsigned long r4; - unsigned long r3; - unsigned long r2; - unsigned long r1; - unsigned long r0; - - /* Only saved on system call */ - unsigned long r12_orig; -}; - - -#endif /* ! __ASSEMBLY__ */ - -#endif /* _UAPI__ASM_AVR32_PTRACE_H */ diff --git a/arch/avr32/include/uapi/asm/sembuf.h b/arch/avr32/include/uapi/asm/sembuf.h deleted file mode 100644 index 6c6f7cf1e75a..000000000000 --- a/arch/avr32/include/uapi/asm/sembuf.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_SEMBUF_H -#define _UAPI__ASM_AVR32_SEMBUF_H - -/* -* The semid64_ds structure for AVR32 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - unsigned long __unused1; - __kernel_time_t sem_ctime; /* last change time */ - unsigned long __unused2; - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _UAPI__ASM_AVR32_SEMBUF_H */ diff --git a/arch/avr32/include/uapi/asm/setup.h b/arch/avr32/include/uapi/asm/setup.h deleted file mode 100644 index a654df7dba46..000000000000 --- a/arch/avr32/include/uapi/asm/setup.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * Based on linux/include/asm-arm/setup.h - * Copyright (C) 1997-1999 Russell King - * - * 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 _UAPI__ASM_AVR32_SETUP_H__ -#define _UAPI__ASM_AVR32_SETUP_H__ - -#define COMMAND_LINE_SIZE 256 - -#endif /* _UAPI__ASM_AVR32_SETUP_H__ */ diff --git a/arch/avr32/include/uapi/asm/shmbuf.h b/arch/avr32/include/uapi/asm/shmbuf.h deleted file mode 100644 index b94cf8b60b73..000000000000 --- a/arch/avr32/include/uapi/asm/shmbuf.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_SHMBUF_H -#define _UAPI__ASM_AVR32_SHMBUF_H - -/* - * The shmid64_ds structure for i386 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_time_t shm_atime; /* last attach time */ - unsigned long __unused1; - __kernel_time_t shm_dtime; /* last detach time */ - unsigned long __unused2; - __kernel_time_t shm_ctime; /* last change time */ - unsigned long __unused3; - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused4; - unsigned long __unused5; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _UAPI__ASM_AVR32_SHMBUF_H */ diff --git a/arch/avr32/include/uapi/asm/sigcontext.h b/arch/avr32/include/uapi/asm/sigcontext.h deleted file mode 100644 index 27e56bf6377f..000000000000 --- a/arch/avr32/include/uapi/asm/sigcontext.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_SIGCONTEXT_H -#define _UAPI__ASM_AVR32_SIGCONTEXT_H - -struct sigcontext { - unsigned long oldmask; - - /* CPU registers */ - unsigned long sr; - unsigned long pc; - unsigned long lr; - unsigned long sp; - unsigned long r12; - unsigned long r11; - unsigned long r10; - unsigned long r9; - unsigned long r8; - unsigned long r7; - unsigned long r6; - unsigned long r5; - unsigned long r4; - unsigned long r3; - unsigned long r2; - unsigned long r1; - unsigned long r0; -}; - -#endif /* _UAPI__ASM_AVR32_SIGCONTEXT_H */ diff --git a/arch/avr32/include/uapi/asm/signal.h b/arch/avr32/include/uapi/asm/signal.h deleted file mode 100644 index ffe8c770cafd..000000000000 --- a/arch/avr32/include/uapi/asm/signal.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_SIGNAL_H -#define _UAPI__ASM_AVR32_SIGNAL_H - -#include <linux/types.h> - -/* Avoid too many header ordering problems. */ -struct siginfo; - -#ifndef __KERNEL__ -/* Here we must cater to libcs that poke about in kernel headers. */ - -#define NSIG 32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) - -/* - * SA_FLAGS values: - * - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_SIGINFO deliver the signal with SIGINFO structs - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NODEFER prevents the current signal from being masked in the handler. - * SA_RESETHAND clears the handler when the signal is delivered. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 -#define SA_SIGINFO 0x00000004 -#define SA_RESTORER 0x04000000 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#include <asm-generic/signal-defs.h> - -#ifndef __KERNEL__ -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void __user *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#endif /* _UAPI__ASM_AVR32_SIGNAL_H */ diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h deleted file mode 100644 index 5a650426f357..000000000000 --- a/arch/avr32/include/uapi/asm/socket.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_SOCKET_H -#define _UAPI__ASM_AVR32_SOCKET_H - -#include <asm/sockios.h> - -/* For setsockopt(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_SNDBUFFORCE 32 -#define SO_RCVBUFFORCE 33 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -#define SO_REUSEPORT 15 -#define SO_PASSCRED 16 -#define SO_PEERCRED 17 -#define SO_RCVLOWAT 18 -#define SO_SNDLOWAT 19 -#define SO_RCVTIMEO 20 -#define SO_SNDTIMEO 21 - -/* Security levels - as per NRL IPv6 - don't actually do anything */ -#define SO_SECURITY_AUTHENTICATION 22 -#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 -#define SO_SECURITY_ENCRYPTION_NETWORK 24 - -#define SO_BINDTODEVICE 25 - -/* Socket filtering */ -#define SO_ATTACH_FILTER 26 -#define SO_DETACH_FILTER 27 -#define SO_GET_FILTER SO_ATTACH_FILTER - -#define SO_PEERNAME 28 -#define SO_TIMESTAMP 29 -#define SCM_TIMESTAMP SO_TIMESTAMP - -#define SO_ACCEPTCONN 30 - -#define SO_PEERSEC 31 -#define SO_PASSSEC 34 -#define SO_TIMESTAMPNS 35 -#define SCM_TIMESTAMPNS SO_TIMESTAMPNS - -#define SO_MARK 36 - -#define SO_TIMESTAMPING 37 -#define SCM_TIMESTAMPING SO_TIMESTAMPING - -#define SO_PROTOCOL 38 -#define SO_DOMAIN 39 - -#define SO_RXQ_OVFL 40 - -#define SO_WIFI_STATUS 41 -#define SCM_WIFI_STATUS SO_WIFI_STATUS -#define SO_PEEK_OFF 42 - -/* Instruct lower device to use last 4-bytes of skb data as FCS */ -#define SO_NOFCS 43 - -#define SO_LOCK_FILTER 44 - -#define SO_SELECT_ERR_QUEUE 45 - -#define SO_BUSY_POLL 46 - -#define SO_MAX_PACING_RATE 47 - -#define SO_BPF_EXTENSIONS 48 - -#define SO_INCOMING_CPU 49 - -#define SO_ATTACH_BPF 50 -#define SO_DETACH_BPF SO_DETACH_FILTER - -#define SO_ATTACH_REUSEPORT_CBPF 51 -#define SO_ATTACH_REUSEPORT_EBPF 52 - -#define SO_CNX_ADVICE 53 - -#define SCM_TIMESTAMPING_OPT_STATS 54 - -#endif /* _UAPI__ASM_AVR32_SOCKET_H */ diff --git a/arch/avr32/include/uapi/asm/sockios.h b/arch/avr32/include/uapi/asm/sockios.h deleted file mode 100644 index d04785453532..000000000000 --- a/arch/avr32/include/uapi/asm/sockios.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_SOCKIOS_H -#define _UAPI__ASM_AVR32_SOCKIOS_H - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ -#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ - -#endif /* _UAPI__ASM_AVR32_SOCKIOS_H */ diff --git a/arch/avr32/include/uapi/asm/stat.h b/arch/avr32/include/uapi/asm/stat.h deleted file mode 100644 index c06acef7fce7..000000000000 --- a/arch/avr32/include/uapi/asm/stat.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_STAT_H -#define _UAPI__ASM_AVR32_STAT_H - -struct __old_kernel_stat { - unsigned short st_dev; - unsigned short st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned long st_size; - unsigned long st_atime; - unsigned long st_mtime; - unsigned long st_ctime; -}; - -struct stat { - unsigned long st_dev; - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned long st_rdev; - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long __unused4; - unsigned long __unused5; -}; - -#define STAT_HAVE_NSEC 1 - -struct stat64 { - unsigned long long st_dev; - - unsigned long long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - - unsigned long st_uid; - unsigned long st_gid; - - unsigned long long st_rdev; - - long long st_size; - unsigned long __pad1; /* align 64-bit st_blocks */ - unsigned long st_blksize; - - unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ - - unsigned long st_atime; - unsigned long st_atime_nsec; - - unsigned long st_mtime; - unsigned long st_mtime_nsec; - - unsigned long st_ctime; - unsigned long st_ctime_nsec; - - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _UAPI__ASM_AVR32_STAT_H */ diff --git a/arch/avr32/include/uapi/asm/swab.h b/arch/avr32/include/uapi/asm/swab.h deleted file mode 100644 index 1a03549e7dc5..000000000000 --- a/arch/avr32/include/uapi/asm/swab.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * AVR32 byteswapping functions. - */ -#ifndef _UAPI__ASM_AVR32_SWAB_H -#define _UAPI__ASM_AVR32_SWAB_H - -#include <linux/types.h> -#include <linux/compiler.h> - -#define __SWAB_64_THRU_32__ - -#ifdef __CHECKER__ -extern unsigned long __builtin_bswap_32(unsigned long x); -extern unsigned short __builtin_bswap_16(unsigned short x); -#endif - -/* - * avr32-linux-gcc versions earlier than 4.2 improperly sign-extends - * the result. - */ -#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) -static inline __attribute_const__ __u16 __arch_swab16(__u16 val) -{ - return __builtin_bswap_16(val); -} -#define __arch_swab16 __arch_swab16 - -static inline __attribute_const__ __u32 __arch_swab32(__u32 val) -{ - return __builtin_bswap_32(val); -} -#define __arch_swab32 __arch_swab32 -#endif - -#endif /* _UAPI__ASM_AVR32_SWAB_H */ diff --git a/arch/avr32/include/uapi/asm/termbits.h b/arch/avr32/include/uapi/asm/termbits.h deleted file mode 100644 index 32789ccb38f8..000000000000 --- a/arch/avr32/include/uapi/asm/termbits.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef _UAPI__ASM_AVR32_TERMBITS_H -#define _UAPI__ASM_AVR32_TERMBITS_H - -#include <linux/posix_types.h> - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ -}; - -struct termios2 { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -struct ktermios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -/* c_iflag bits */ -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define XTABS 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -/* c_cflag bit meaning */ -#define CBAUD 0010017 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 -#define CBAUDEX 0010000 -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate (not used) */ -#define CMSPAR 010000000000 /* mark or space (stick) parity */ -#define CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 -#define EXTPROC 0200000 - -/* tcflow() and TCXONC use these */ -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#endif /* _UAPI__ASM_AVR32_TERMBITS_H */ diff --git a/arch/avr32/include/uapi/asm/termios.h b/arch/avr32/include/uapi/asm/termios.h deleted file mode 100644 index c8a0081556c4..000000000000 --- a/arch/avr32/include/uapi/asm/termios.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_TERMIOS_H -#define _UAPI__ASM_AVR32_TERMIOS_H - -#include <asm/termbits.h> -#include <asm/ioctls.h> - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -#endif /* _UAPI__ASM_AVR32_TERMIOS_H */ diff --git a/arch/avr32/include/uapi/asm/types.h b/arch/avr32/include/uapi/asm/types.h deleted file mode 100644 index 7c986c4e99b5..000000000000 --- a/arch/avr32/include/uapi/asm/types.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_TYPES_H -#define _UAPI__ASM_AVR32_TYPES_H - -#include <asm-generic/int-ll64.h> - -#endif /* _UAPI__ASM_AVR32_TYPES_H */ diff --git a/arch/avr32/include/uapi/asm/unistd.h b/arch/avr32/include/uapi/asm/unistd.h deleted file mode 100644 index 236505d889d0..000000000000 --- a/arch/avr32/include/uapi/asm/unistd.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 _UAPI__ASM_AVR32_UNISTD_H -#define _UAPI__ASM_AVR32_UNISTD_H - -/* - * This file contains the system call numbers. - */ - -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_umask 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_chown 16 -#define __NR_lchown 17 -#define __NR_lseek 18 -#define __NR__llseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount2 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_pause 28 -#define __NR_utime 29 -#define __NR_stat 30 -#define __NR_fstat 31 -#define __NR_lstat 32 -#define __NR_access 33 -#define __NR_chroot 34 -#define __NR_sync 35 -#define __NR_fsync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_clone 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_getcwd 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_setfsuid 52 -#define __NR_setfsgid 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_setpgid 56 -#define __NR_mremap 57 -#define __NR_setresuid 58 -#define __NR_getresuid 59 -#define __NR_setreuid 60 -#define __NR_setregid 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_rt_sigaction 67 -#define __NR_rt_sigreturn 68 -#define __NR_rt_sigprocmask 69 -#define __NR_rt_sigpending 70 -#define __NR_rt_sigtimedwait 71 -#define __NR_rt_sigqueueinfo 72 -#define __NR_rt_sigsuspend 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 /* SuS compliant getrlimit */ -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_fchdir 84 -#define __NR_readlink 85 -#define __NR_pread 86 -#define __NR_pwrite 87 -#define __NR_swapon 88 -#define __NR_reboot 89 -#define __NR_mmap2 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_wait4 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_vhangup 101 -#define __NR_sigaltstack 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_swapoff 106 -#define __NR_sysinfo 107 -/* 108 was __NR_ipc for a little while */ -#define __NR_sendfile 109 -#define __NR_setdomainname 110 -#define __NR_uname 111 -#define __NR_adjtimex 112 -#define __NR_mprotect 113 -#define __NR_vfork 114 -#define __NR_init_module 115 -#define __NR_delete_module 116 -#define __NR_quotactl 117 -#define __NR_getpgid 118 -#define __NR_bdflush 119 -#define __NR_sysfs 120 -#define __NR_personality 121 -#define __NR_afs_syscall 122 /* Syscall for Andrew File System */ -#define __NR_getdents 123 -#define __NR_flock 124 -#define __NR_msync 125 -#define __NR_readv 126 -#define __NR_writev 127 -#define __NR_getsid 128 -#define __NR_fdatasync 129 -#define __NR__sysctl 130 -#define __NR_mlock 131 -#define __NR_munlock 132 -#define __NR_mlockall 133 -#define __NR_munlockall 134 -#define __NR_sched_setparam 135 -#define __NR_sched_getparam 136 -#define __NR_sched_setscheduler 137 -#define __NR_sched_getscheduler 138 -#define __NR_sched_yield 139 -#define __NR_sched_get_priority_max 140 -#define __NR_sched_get_priority_min 141 -#define __NR_sched_rr_get_interval 142 -#define __NR_nanosleep 143 -#define __NR_poll 144 -#define __NR_nfsservctl 145 -#define __NR_setresgid 146 -#define __NR_getresgid 147 -#define __NR_prctl 148 -#define __NR_socket 149 -#define __NR_bind 150 -#define __NR_connect 151 -#define __NR_listen 152 -#define __NR_accept 153 -#define __NR_getsockname 154 -#define __NR_getpeername 155 -#define __NR_socketpair 156 -#define __NR_send 157 -#define __NR_recv 158 -#define __NR_sendto 159 -#define __NR_recvfrom 160 -#define __NR_shutdown 161 -#define __NR_setsockopt 162 -#define __NR_getsockopt 163 -#define __NR_sendmsg 164 -#define __NR_recvmsg 165 -#define __NR_truncate64 166 -#define __NR_ftruncate64 167 -#define __NR_stat64 168 -#define __NR_lstat64 169 -#define __NR_fstat64 170 -#define __NR_pivot_root 171 -#define __NR_mincore 172 -#define __NR_madvise 173 -#define __NR_getdents64 174 -#define __NR_fcntl64 175 -#define __NR_gettid 176 -#define __NR_readahead 177 -#define __NR_setxattr 178 -#define __NR_lsetxattr 179 -#define __NR_fsetxattr 180 -#define __NR_getxattr 181 -#define __NR_lgetxattr 182 -#define __NR_fgetxattr 183 -#define __NR_listxattr 184 -#define __NR_llistxattr 185 -#define __NR_flistxattr 186 -#define __NR_removexattr 187 -#define __NR_lremovexattr 188 -#define __NR_fremovexattr 189 -#define __NR_tkill 190 -#define __NR_sendfile64 191 -#define __NR_futex 192 -#define __NR_sched_setaffinity 193 -#define __NR_sched_getaffinity 194 -#define __NR_capget 195 -#define __NR_capset 196 -#define __NR_io_setup 197 -#define __NR_io_destroy 198 -#define __NR_io_getevents 199 -#define __NR_io_submit 200 -#define __NR_io_cancel 201 -#define __NR_fadvise64 202 -#define __NR_exit_group 203 -#define __NR_lookup_dcookie 204 -#define __NR_epoll_create 205 -#define __NR_epoll_ctl 206 -#define __NR_epoll_wait 207 -#define __NR_remap_file_pages 208 -#define __NR_set_tid_address 209 -#define __NR_timer_create 210 -#define __NR_timer_settime 211 -#define __NR_timer_gettime 212 -#define __NR_timer_getoverrun 213 -#define __NR_timer_delete 214 -#define __NR_clock_settime 215 -#define __NR_clock_gettime 216 -#define __NR_clock_getres 217 -#define __NR_clock_nanosleep 218 -#define __NR_statfs64 219 -#define __NR_fstatfs64 220 -#define __NR_tgkill 221 -/* 222 reserved for tux */ -#define __NR_utimes 223 -#define __NR_fadvise64_64 224 -#define __NR_cacheflush 225 -#define __NR_vserver 226 -#define __NR_mq_open 227 -#define __NR_mq_unlink 228 -#define __NR_mq_timedsend 229 -#define __NR_mq_timedreceive 230 -#define __NR_mq_notify 231 -#define __NR_mq_getsetattr 232 -#define __NR_kexec_load 233 -#define __NR_waitid 234 -#define __NR_add_key 235 -#define __NR_request_key 236 -#define __NR_keyctl 237 -#define __NR_ioprio_set 238 -#define __NR_ioprio_get 239 -#define __NR_inotify_init 240 -#define __NR_inotify_add_watch 241 -#define __NR_inotify_rm_watch 242 -#define __NR_openat 243 -#define __NR_mkdirat 244 -#define __NR_mknodat 245 -#define __NR_fchownat 246 -#define __NR_futimesat 247 -#define __NR_fstatat64 248 -#define __NR_unlinkat 249 -#define __NR_renameat 250 -#define __NR_linkat 251 -#define __NR_symlinkat 252 -#define __NR_readlinkat 253 -#define __NR_fchmodat 254 -#define __NR_faccessat 255 -#define __NR_pselect6 256 -#define __NR_ppoll 257 -#define __NR_unshare 258 -#define __NR_set_robust_list 259 -#define __NR_get_robust_list 260 -#define __NR_splice 261 -#define __NR_sync_file_range 262 -#define __NR_tee 263 -#define __NR_vmsplice 264 -#define __NR_epoll_pwait 265 -#define __NR_msgget 266 -#define __NR_msgsnd 267 -#define __NR_msgrcv 268 -#define __NR_msgctl 269 -#define __NR_semget 270 -#define __NR_semop 271 -#define __NR_semctl 272 -#define __NR_semtimedop 273 -#define __NR_shmat 274 -#define __NR_shmget 275 -#define __NR_shmdt 276 -#define __NR_shmctl 277 -#define __NR_utimensat 278 -#define __NR_signalfd 279 -/* 280 was __NR_timerfd */ -#define __NR_eventfd 281 -/* 282 was half-implemented __NR_recvmmsg */ -#define __NR_setns 283 -#define __NR_pread64 284 -#define __NR_pwrite64 285 -#define __NR_timerfd_create 286 -#define __NR_fallocate 287 -#define __NR_timerfd_settime 288 -#define __NR_timerfd_gettime 289 -#define __NR_signalfd4 290 -#define __NR_eventfd2 291 -#define __NR_epoll_create1 292 -#define __NR_dup3 293 -#define __NR_pipe2 294 -#define __NR_inotify_init1 295 -#define __NR_preadv 296 -#define __NR_pwritev 297 -#define __NR_rt_tgsigqueueinfo 298 -#define __NR_perf_event_open 299 -#define __NR_recvmmsg 300 -#define __NR_fanotify_init 301 -#define __NR_fanotify_mark 302 -#define __NR_prlimit64 303 -#define __NR_name_to_handle_at 304 -#define __NR_open_by_handle_at 305 -#define __NR_clock_adjtime 306 -#define __NR_syncfs 307 -#define __NR_sendmmsg 308 -#define __NR_process_vm_readv 309 -#define __NR_process_vm_writev 310 -#define __NR_kcmp 311 -#define __NR_finit_module 312 -#define __NR_sched_setattr 313 -#define __NR_sched_getattr 314 -#define __NR_renameat2 315 -#define __NR_seccomp 316 -#define __NR_getrandom 317 -#define __NR_memfd_create 318 -#define __NR_bpf 319 -#define __NR_execveat 320 -#define __NR_accept4 321 -#define __NR_userfaultfd 322 -#define __NR_membarrier 323 -#define __NR_mlock2 324 -#define __NR_copy_file_range 325 -#define __NR_preadv2 326 -#define __NR_pwritev2 327 -#define __NR_pkey_mprotect 328 -#define __NR_pkey_alloc 329 -#define __NR_pkey_free 330 - -#endif /* _UAPI__ASM_AVR32_UNISTD_H */ diff --git a/arch/avr32/kernel/.gitignore b/arch/avr32/kernel/.gitignore deleted file mode 100644 index c5f676c3c224..000000000000 --- a/arch/avr32/kernel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vmlinux.lds diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile deleted file mode 100644 index 119a2e41defe..000000000000 --- a/arch/avr32/kernel/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for the Linux/AVR32 kernel. -# - -extra-y := head.o vmlinux.lds - -obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o -obj-y += syscall_table.o syscall-stubs.o irq.o -obj-y += setup.o traps.o ocd.o ptrace.o -obj-y += signal.o process.o time.o -obj-y += switch_to.o cpu.o -obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o -obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_NMI_DEBUGGING) += nmi_debug.o diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c deleted file mode 100644 index 2c9764fe3532..000000000000 --- a/arch/avr32/kernel/asm-offsets.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Generate definitions needed by assembly language modules. - * This code generates raw asm output which is post-processed - * to extract and format the required data. - */ - -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/thread_info.h> -#include <linux/kbuild.h> - -void foo(void) -{ - OFFSET(TI_task, thread_info, task); - OFFSET(TI_flags, thread_info, flags); - OFFSET(TI_cpu, thread_info, cpu); - OFFSET(TI_preempt_count, thread_info, preempt_count); - OFFSET(TI_rar_saved, thread_info, rar_saved); - OFFSET(TI_rsr_saved, thread_info, rsr_saved); - BLANK(); - OFFSET(TSK_active_mm, task_struct, active_mm); - BLANK(); - OFFSET(MM_pgd, mm_struct, pgd); -} diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c deleted file mode 100644 index 0d05fd095468..000000000000 --- a/arch/avr32/kernel/avr32_ksyms.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Export AVR32-specific functions for loadable modules. - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/delay.h> -#include <linux/io.h> -#include <linux/module.h> - -#include <asm/checksum.h> -#include <linux/uaccess.h> - -/* - * GCC functions - */ -extern unsigned long long __avr32_lsl64(unsigned long long u, unsigned long b); -extern unsigned long long __avr32_lsr64(unsigned long long u, unsigned long b); -extern unsigned long long __avr32_asr64(unsigned long long u, unsigned long b); -EXPORT_SYMBOL(__avr32_lsl64); -EXPORT_SYMBOL(__avr32_lsr64); -EXPORT_SYMBOL(__avr32_asr64); - -/* - * String functions - */ -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcpy); - -EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(copy_page); - -/* - * Userspace access stuff. - */ -EXPORT_SYMBOL(___copy_from_user); -EXPORT_SYMBOL(copy_to_user); -EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(strncpy_from_user); -EXPORT_SYMBOL(__strncpy_from_user); -EXPORT_SYMBOL(clear_user); -EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(strnlen_user); - -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_generic); - -/* Delay loops (lib/delay.S) */ -EXPORT_SYMBOL(__ndelay); -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__const_udelay); - -/* Bit operations (lib/findbit.S) */ -EXPORT_SYMBOL(find_first_zero_bit); -EXPORT_SYMBOL(find_next_zero_bit); -EXPORT_SYMBOL(find_first_bit); -EXPORT_SYMBOL(find_next_bit); -EXPORT_SYMBOL(find_next_bit_le); -EXPORT_SYMBOL(find_next_zero_bit_le); - -/* I/O primitives (lib/io-*.S) */ -EXPORT_SYMBOL(__raw_readsb); -EXPORT_SYMBOL(__raw_readsw); -EXPORT_SYMBOL(__raw_readsl); -EXPORT_SYMBOL(__raw_writesb); -EXPORT_SYMBOL(__raw_writesw); -EXPORT_SYMBOL(__raw_writesl); diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c deleted file mode 100644 index 0341ae27c9ec..000000000000 --- a/arch/avr32/kernel/cpu.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/init.h> -#include <linux/device.h> -#include <linux/seq_file.h> -#include <linux/cpu.h> -#include <linux/module.h> -#include <linux/percpu.h> -#include <linux/param.h> -#include <linux/errno.h> -#include <linux/clk.h> - -#include <asm/setup.h> -#include <asm/sysreg.h> - -static DEFINE_PER_CPU(struct cpu, cpu_devices); - -#ifdef CONFIG_PERFORMANCE_COUNTERS - -/* - * XXX: If/when a SMP-capable implementation of AVR32 will ever be - * made, we must make sure that the code executes on the correct CPU. - */ -static ssize_t show_pc0event(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned long pccr; - - pccr = sysreg_read(PCCR); - return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f); -} -static ssize_t store_pc0event(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) - return ret; - if (val > 0x3f) - return -EINVAL; - val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff); - sysreg_write(PCCR, val); - return count; -} -static ssize_t show_pc0count(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned long pcnt0; - - pcnt0 = sysreg_read(PCNT0); - return sprintf(buf, "%lu\n", pcnt0); -} -static ssize_t store_pc0count(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) - return ret; - sysreg_write(PCNT0, val); - - return count; -} - -static ssize_t show_pc1event(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned long pccr; - - pccr = sysreg_read(PCCR); - return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f); -} -static ssize_t store_pc1event(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) - return ret; - if (val > 0x3f) - return -EINVAL; - val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff); - sysreg_write(PCCR, val); - return count; -} -static ssize_t show_pc1count(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned long pcnt1; - - pcnt1 = sysreg_read(PCNT1); - return sprintf(buf, "%lu\n", pcnt1); -} -static ssize_t store_pc1count(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) - return ret; - sysreg_write(PCNT1, val); - - return count; -} - -static ssize_t show_pccycles(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned long pccnt; - - pccnt = sysreg_read(PCCNT); - return sprintf(buf, "%lu\n", pccnt); -} -static ssize_t store_pccycles(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) - return ret; - sysreg_write(PCCNT, val); - - return count; -} - -static ssize_t show_pcenable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned long pccr; - - pccr = sysreg_read(PCCR); - return sprintf(buf, "%c\n", (pccr & 1)?'1':'0'); -} -static ssize_t store_pcenable(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long pccr, val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) - return ret; - if (val) - val = 1; - - pccr = sysreg_read(PCCR); - pccr = (pccr & ~1UL) | val; - sysreg_write(PCCR, pccr); - - return count; -} - -static DEVICE_ATTR(pc0event, 0600, show_pc0event, store_pc0event); -static DEVICE_ATTR(pc0count, 0600, show_pc0count, store_pc0count); -static DEVICE_ATTR(pc1event, 0600, show_pc1event, store_pc1event); -static DEVICE_ATTR(pc1count, 0600, show_pc1count, store_pc1count); -static DEVICE_ATTR(pccycles, 0600, show_pccycles, store_pccycles); -static DEVICE_ATTR(pcenable, 0600, show_pcenable, store_pcenable); - -#endif /* CONFIG_PERFORMANCE_COUNTERS */ - -static int __init topology_init(void) -{ - int cpu; - - for_each_possible_cpu(cpu) { - struct cpu *c = &per_cpu(cpu_devices, cpu); - - register_cpu(c, cpu); - -#ifdef CONFIG_PERFORMANCE_COUNTERS - device_create_file(&c->dev, &dev_attr_pc0event); - device_create_file(&c->dev, &dev_attr_pc0count); - device_create_file(&c->dev, &dev_attr_pc1event); - device_create_file(&c->dev, &dev_attr_pc1count); - device_create_file(&c->dev, &dev_attr_pccycles); - device_create_file(&c->dev, &dev_attr_pcenable); -#endif - } - - return 0; -} - -subsys_initcall(topology_init); - -struct chip_id_map { - u16 mid; - u16 pn; - const char *name; -}; - -static const struct chip_id_map chip_names[] = { - { .mid = 0x1f, .pn = 0x1e82, .name = "AT32AP700x" }, -}; -#define NR_CHIP_NAMES ARRAY_SIZE(chip_names) - -static const char *cpu_names[] = { - "Morgan", - "AP7", -}; -#define NR_CPU_NAMES ARRAY_SIZE(cpu_names) - -static const char *arch_names[] = { - "AVR32A", - "AVR32B", -}; -#define NR_ARCH_NAMES ARRAY_SIZE(arch_names) - -static const char *mmu_types[] = { - "No MMU", - "ITLB and DTLB", - "Shared TLB", - "MPU" -}; - -static const char *cpu_feature_flags[] = { - "rmw", "dsp", "simd", "ocd", "perfctr", "java", "fpu", -}; - -static const char *get_chip_name(struct avr32_cpuinfo *cpu) -{ - unsigned int i; - unsigned int mid = avr32_get_manufacturer_id(cpu); - unsigned int pn = avr32_get_product_number(cpu); - - for (i = 0; i < NR_CHIP_NAMES; i++) { - if (chip_names[i].mid == mid && chip_names[i].pn == pn) - return chip_names[i].name; - } - - return "(unknown)"; -} - -void __init setup_processor(void) -{ - unsigned long config0, config1; - unsigned long features; - unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type; - unsigned device_id; - unsigned tmp; - unsigned i; - - config0 = sysreg_read(CONFIG0); - config1 = sysreg_read(CONFIG1); - cpu_id = SYSREG_BFEXT(PROCESSORID, config0); - cpu_rev = SYSREG_BFEXT(PROCESSORREVISION, config0); - arch_id = SYSREG_BFEXT(AT, config0); - arch_rev = SYSREG_BFEXT(AR, config0); - mmu_type = SYSREG_BFEXT(MMUT, config0); - - device_id = ocd_read(DID); - - boot_cpu_data.arch_type = arch_id; - boot_cpu_data.cpu_type = cpu_id; - boot_cpu_data.arch_revision = arch_rev; - boot_cpu_data.cpu_revision = cpu_rev; - boot_cpu_data.tlb_config = mmu_type; - boot_cpu_data.device_id = device_id; - - tmp = SYSREG_BFEXT(ILSZ, config1); - if (tmp) { - boot_cpu_data.icache.ways = 1 << SYSREG_BFEXT(IASS, config1); - boot_cpu_data.icache.sets = 1 << SYSREG_BFEXT(ISET, config1); - boot_cpu_data.icache.linesz = 1 << (tmp + 1); - } - tmp = SYSREG_BFEXT(DLSZ, config1); - if (tmp) { - boot_cpu_data.dcache.ways = 1 << SYSREG_BFEXT(DASS, config1); - boot_cpu_data.dcache.sets = 1 << SYSREG_BFEXT(DSET, config1); - boot_cpu_data.dcache.linesz = 1 << (tmp + 1); - } - - if ((cpu_id >= NR_CPU_NAMES) || (arch_id >= NR_ARCH_NAMES)) { - printk ("Unknown CPU configuration (ID %02x, arch %02x), " - "continuing anyway...\n", - cpu_id, arch_id); - return; - } - - printk ("CPU: %s chip revision %c\n", get_chip_name(&boot_cpu_data), - avr32_get_chip_revision(&boot_cpu_data) + 'A'); - printk ("CPU: %s [%02x] core revision %d (%s arch revision %d)\n", - cpu_names[cpu_id], cpu_id, cpu_rev, - arch_names[arch_id], arch_rev); - printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]); - - printk ("CPU: features:"); - features = 0; - if (config0 & SYSREG_BIT(CONFIG0_R)) - features |= AVR32_FEATURE_RMW; - if (config0 & SYSREG_BIT(CONFIG0_D)) - features |= AVR32_FEATURE_DSP; - if (config0 & SYSREG_BIT(CONFIG0_S)) - features |= AVR32_FEATURE_SIMD; - if (config0 & SYSREG_BIT(CONFIG0_O)) - features |= AVR32_FEATURE_OCD; - if (config0 & SYSREG_BIT(CONFIG0_P)) - features |= AVR32_FEATURE_PCTR; - if (config0 & SYSREG_BIT(CONFIG0_J)) - features |= AVR32_FEATURE_JAVA; - if (config0 & SYSREG_BIT(CONFIG0_F)) - features |= AVR32_FEATURE_FPU; - - for (i = 0; i < ARRAY_SIZE(cpu_feature_flags); i++) - if (features & (1 << i)) - printk(" %s", cpu_feature_flags[i]); - - printk("\n"); - boot_cpu_data.features = features; -} - -#ifdef CONFIG_PROC_FS -static int c_show(struct seq_file *m, void *v) -{ - unsigned int icache_size, dcache_size; - unsigned int cpu = smp_processor_id(); - unsigned int freq; - unsigned int i; - - icache_size = boot_cpu_data.icache.ways * - boot_cpu_data.icache.sets * - boot_cpu_data.icache.linesz; - dcache_size = boot_cpu_data.dcache.ways * - boot_cpu_data.dcache.sets * - boot_cpu_data.dcache.linesz; - - seq_printf(m, "processor\t: %d\n", cpu); - - seq_printf(m, "chip type\t: %s revision %c\n", - get_chip_name(&boot_cpu_data), - avr32_get_chip_revision(&boot_cpu_data) + 'A'); - if (boot_cpu_data.arch_type < NR_ARCH_NAMES) - seq_printf(m, "cpu arch\t: %s revision %d\n", - arch_names[boot_cpu_data.arch_type], - boot_cpu_data.arch_revision); - if (boot_cpu_data.cpu_type < NR_CPU_NAMES) - seq_printf(m, "cpu core\t: %s revision %d\n", - cpu_names[boot_cpu_data.cpu_type], - boot_cpu_data.cpu_revision); - - freq = (clk_get_rate(boot_cpu_data.clk) + 500) / 1000; - seq_printf(m, "cpu MHz\t\t: %u.%03u\n", freq / 1000, freq % 1000); - - seq_printf(m, "i-cache\t\t: %dK (%u ways x %u sets x %u)\n", - icache_size >> 10, - boot_cpu_data.icache.ways, - boot_cpu_data.icache.sets, - boot_cpu_data.icache.linesz); - seq_printf(m, "d-cache\t\t: %dK (%u ways x %u sets x %u)\n", - dcache_size >> 10, - boot_cpu_data.dcache.ways, - boot_cpu_data.dcache.sets, - boot_cpu_data.dcache.linesz); - - seq_printf(m, "features\t:"); - for (i = 0; i < ARRAY_SIZE(cpu_feature_flags); i++) - if (boot_cpu_data.features & (1 << i)) - seq_printf(m, " %s", cpu_feature_flags[i]); - - seq_printf(m, "\nbogomips\t: %lu.%02lu\n", - boot_cpu_data.loops_per_jiffy / (500000/HZ), - (boot_cpu_data.loops_per_jiffy / (5000/HZ)) % 100); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; -} - -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} - -static void c_stop(struct seq_file *m, void *v) -{ - -} - -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = c_show -}; -#endif /* CONFIG_PROC_FS */ diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S deleted file mode 100644 index 7301f4806bbe..000000000000 --- a/arch/avr32/kernel/entry-avr32b.S +++ /dev/null @@ -1,877 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - -/* - * This file contains the low-level entry-points into the kernel, that is, - * exception handlers, debug trap handlers, interrupt handlers and the - * system call handler. - */ -#include <linux/errno.h> - -#include <asm/asm.h> -#include <asm/hardirq.h> -#include <asm/irq.h> -#include <asm/ocd.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/ptrace.h> -#include <asm/sysreg.h> -#include <asm/thread_info.h> -#include <asm/unistd.h> - -#ifdef CONFIG_PREEMPT -# define preempt_stop mask_interrupts -#else -# define preempt_stop -# define fault_resume_kernel fault_restore_all -#endif - -#define __MASK(x) ((1 << (x)) - 1) -#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \ - (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)) - - .section .ex.text,"ax",@progbits - .align 2 -exception_vectors: - bral handle_critical - .align 2 - bral handle_critical - .align 2 - bral do_bus_error_write - .align 2 - bral do_bus_error_read - .align 2 - bral do_nmi_ll - .align 2 - bral handle_address_fault - .align 2 - bral handle_protection_fault - .align 2 - bral handle_debug - .align 2 - bral do_illegal_opcode_ll - .align 2 - bral do_illegal_opcode_ll - .align 2 - bral do_illegal_opcode_ll - .align 2 - bral do_fpe_ll - .align 2 - bral do_illegal_opcode_ll - .align 2 - bral handle_address_fault - .align 2 - bral handle_address_fault - .align 2 - bral handle_protection_fault - .align 2 - bral handle_protection_fault - .align 2 - bral do_dtlb_modified - -#define tlbmiss_save pushm r0-r3 -#define tlbmiss_restore popm r0-r3 - - .org 0x50 - .global itlb_miss -itlb_miss: - tlbmiss_save - rjmp tlb_miss_common - - .org 0x60 -dtlb_miss_read: - tlbmiss_save - rjmp tlb_miss_common - - .org 0x70 -dtlb_miss_write: - tlbmiss_save - - .global tlb_miss_common - .align 2 -tlb_miss_common: - mfsr r0, SYSREG_TLBEAR - mfsr r1, SYSREG_PTBR - - /* - * First level lookup: The PGD contains virtual pointers to - * the second-level page tables, but they may be NULL if not - * present. - */ -pgtbl_lookup: - lsr r2, r0, PGDIR_SHIFT - ld.w r3, r1[r2 << 2] - bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT - cp.w r3, 0 - breq page_table_not_present - - /* Second level lookup */ - ld.w r2, r3[r1 << 2] - mfsr r0, SYSREG_TLBARLO - bld r2, _PAGE_BIT_PRESENT - brcc page_not_present - - /* Mark the page as accessed */ - sbr r2, _PAGE_BIT_ACCESSED - st.w r3[r1 << 2], r2 - - /* Drop software flags */ - andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff - mtsr SYSREG_TLBELO, r2 - - /* Figure out which entry we want to replace */ - mfsr r1, SYSREG_MMUCR - clz r2, r0 - brcc 1f - mov r3, -1 /* All entries have been accessed, */ - mov r2, 0 /* so start at 0 */ - mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */ - -1: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE - mtsr SYSREG_MMUCR, r1 - tlbw - - tlbmiss_restore - rete - - /* The slow path of the TLB miss handler */ - .align 2 -page_table_not_present: - /* Do we need to synchronize with swapper_pg_dir? */ - bld r0, 31 - brcs sync_with_swapper_pg_dir - -page_not_present: - tlbmiss_restore - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - mfsr r12, SYSREG_ECR - mov r11, sp - call do_page_fault - rjmp ret_from_exception - - .align 2 -sync_with_swapper_pg_dir: - /* - * If swapper_pg_dir contains a non-NULL second-level page - * table pointer, copy it into the current PGD. If not, we - * must handle it as a full-blown page fault. - * - * Jumping back to pgtbl_lookup causes an unnecessary lookup, - * but it is guaranteed to be a cache hit, it won't happen - * very often, and we absolutely do not want to sacrifice any - * performance in the fast path in order to improve this. - */ - mov r1, lo(swapper_pg_dir) - orh r1, hi(swapper_pg_dir) - ld.w r3, r1[r2 << 2] - cp.w r3, 0 - breq page_not_present - mfsr r1, SYSREG_PTBR - st.w r1[r2 << 2], r3 - rjmp pgtbl_lookup - - /* - * We currently have two bytes left at this point until we - * crash into the system call handler... - * - * Don't worry, the assembler will let us know. - */ - - - /* --- System Call --- */ - - .org 0x100 -system_call: -#ifdef CONFIG_PREEMPT - mask_interrupts -#endif - pushm r12 /* r12_orig */ - stmts --sp, r0-lr - - mfsr r0, SYSREG_RAR_SUP - mfsr r1, SYSREG_RSR_SUP -#ifdef CONFIG_PREEMPT - unmask_interrupts -#endif - zero_fp - stm --sp, r0-r1 - - /* check for syscall tracing */ - get_thread_info r0 - ld.w r1, r0[TI_flags] - bld r1, TIF_SYSCALL_TRACE - brcs syscall_trace_enter - -syscall_trace_cont: - cp.w r8, NR_syscalls - brhs syscall_badsys - - lddpc lr, syscall_table_addr - ld.w lr, lr[r8 << 2] - mov r8, r5 /* 5th argument (6th is pushed by stub) */ - icall lr - - .global syscall_return -syscall_return: - get_thread_info r0 - mask_interrupts /* make sure we don't miss an interrupt - setting need_resched or sigpending - between sampling and the rets */ - - /* Store the return value so that the correct value is loaded below */ - stdsp sp[REG_R12], r12 - - ld.w r1, r0[TI_flags] - andl r1, _TIF_ALLWORK_MASK, COH - brne syscall_exit_work - -syscall_exit_cont: - popm r8-r9 - mtsr SYSREG_RAR_SUP, r8 - mtsr SYSREG_RSR_SUP, r9 - ldmts sp++, r0-lr - sub sp, -4 /* r12_orig */ - rets - - .align 2 -syscall_table_addr: - .long sys_call_table - -syscall_badsys: - mov r12, -ENOSYS - rjmp syscall_return - - .global ret_from_fork -ret_from_fork: - call schedule_tail - mov r12, 0 - rjmp syscall_return - - .global ret_from_kernel_thread -ret_from_kernel_thread: - call schedule_tail - mov r12, r0 - mov lr, r2 /* syscall_return */ - mov pc, r1 - -syscall_trace_enter: - pushm r8-r12 - call syscall_trace - popm r8-r12 - rjmp syscall_trace_cont - -syscall_exit_work: - bld r1, TIF_SYSCALL_TRACE - brcc 1f - unmask_interrupts - call syscall_trace - mask_interrupts - ld.w r1, r0[TI_flags] - -1: bld r1, TIF_NEED_RESCHED - brcc 2f - unmask_interrupts - call schedule - mask_interrupts - ld.w r1, r0[TI_flags] - rjmp 1b - -2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME - tst r1, r2 - breq 3f - unmask_interrupts - mov r12, sp - mov r11, r0 - call do_notify_resume - mask_interrupts - ld.w r1, r0[TI_flags] - rjmp 1b - -3: bld r1, TIF_BREAKPOINT - brcc syscall_exit_cont - rjmp enter_monitor_mode - - /* This function expects to find offending PC in SYSREG_RAR_EX */ - .type save_full_context_ex, @function - .align 2 -save_full_context_ex: - mfsr r11, SYSREG_RAR_EX - sub r9, pc, . - debug_trampoline - mfsr r8, SYSREG_RSR_EX - cp.w r9, r11 - breq 3f - mov r12, r8 - andh r8, (MODE_MASK >> 16), COH - brne 2f - -1: pushm r11, r12 /* PC and SR */ - unmask_exceptions - ret r12 - -2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR) - stdsp sp[4], r10 /* replace saved SP */ - rjmp 1b - - /* - * The debug handler set up a trampoline to make us - * automatically enter monitor mode upon return, but since - * we're saving the full context, we must assume that the - * exception handler might want to alter the return address - * and/or status register. So we need to restore the original - * context and enter monitor mode manually after the exception - * has been handled. - */ -3: get_thread_info r8 - ld.w r11, r8[TI_rar_saved] - ld.w r12, r8[TI_rsr_saved] - rjmp 1b - .size save_full_context_ex, . - save_full_context_ex - - /* Low-level exception handlers */ -handle_critical: - /* - * AT32AP700x errata: - * - * After a Java stack overflow or underflow trap, any CPU - * memory access may cause erratic behavior. This will happen - * when the four least significant bits of the JOSP system - * register contains any value between 9 and 15 (inclusive). - * - * Possible workarounds: - * - Don't use the Java Extension Module - * - Ensure that the stack overflow and underflow trap - * handlers do not do any memory access or trigger any - * exceptions before the overflow/underflow condition is - * cleared (by incrementing or decrementing the JOSP) - * - Make sure that JOSP does not contain any problematic - * value before doing any exception or interrupt - * processing. - * - Set up a critical exception handler which writes a - * known-to-be-safe value, e.g. 4, to JOSP before doing - * any further processing. - * - * We'll use the last workaround for now since we cannot - * guarantee that user space processes don't use Java mode. - * Non-well-behaving userland will be terminated with extreme - * prejudice. - */ -#ifdef CONFIG_CPU_AT32AP700X - /* - * There's a chance we can't touch memory, so temporarily - * borrow PTBR to save the stack pointer while we fix things - * up... - */ - mtsr SYSREG_PTBR, sp - mov sp, 4 - mtsr SYSREG_JOSP, sp - mfsr sp, SYSREG_PTBR - sub pc, -2 - - /* Push most of pt_regs on stack. We'll do the rest later */ - sub sp, 4 - pushm r0-r12 - - /* PTBR mirrors current_thread_info()->task->active_mm->pgd */ - get_thread_info r0 - ld.w r1, r0[TI_task] - ld.w r2, r1[TSK_active_mm] - ld.w r3, r2[MM_pgd] - mtsr SYSREG_PTBR, r3 -#else - sub sp, 4 - pushm r0-r12 -#endif - sub r0, sp, -(14 * 4) - mov r1, lr - mfsr r2, SYSREG_RAR_EX - mfsr r3, SYSREG_RSR_EX - pushm r0-r3 - - mfsr r12, SYSREG_ECR - mov r11, sp - call do_critical_exception - - /* We should never get here... */ -bad_return: - sub r12, pc, (. - 1f) - lddpc pc, 2f - .align 2 -1: .asciz "Return from critical exception!" -2: .long panic - - .align 1 -do_bus_error_write: - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - mov r11, 1 - rjmp 1f - -do_bus_error_read: - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - mov r11, 0 -1: mfsr r12, SYSREG_BEAR - mov r10, sp - call do_bus_error - rjmp ret_from_exception - - .align 1 -do_nmi_ll: - sub sp, 4 - stmts --sp, r0-lr - mfsr r9, SYSREG_RSR_NMI - mfsr r8, SYSREG_RAR_NMI - bfextu r0, r9, MODE_SHIFT, 3 - brne 2f - -1: pushm r8, r9 /* PC and SR */ - mfsr r12, SYSREG_ECR - mov r11, sp - call do_nmi - popm r8-r9 - mtsr SYSREG_RAR_NMI, r8 - tst r0, r0 - mtsr SYSREG_RSR_NMI, r9 - brne 3f - - ldmts sp++, r0-lr - sub sp, -4 /* skip r12_orig */ - rete - -2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR) - stdsp sp[4], r10 /* replace saved SP */ - rjmp 1b - -3: popm lr - sub sp, -4 /* skip sp */ - popm r0-r12 - sub sp, -4 /* skip r12_orig */ - rete - -handle_address_fault: - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - mfsr r12, SYSREG_ECR - mov r11, sp - call do_address_exception - rjmp ret_from_exception - -handle_protection_fault: - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - mfsr r12, SYSREG_ECR - mov r11, sp - call do_page_fault - rjmp ret_from_exception - - .align 1 -do_illegal_opcode_ll: - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - mfsr r12, SYSREG_ECR - mov r11, sp - call do_illegal_opcode - rjmp ret_from_exception - -do_dtlb_modified: - pushm r0-r3 - mfsr r1, SYSREG_TLBEAR - mfsr r0, SYSREG_PTBR - lsr r2, r1, PGDIR_SHIFT - ld.w r0, r0[r2 << 2] - lsl r1, (32 - PGDIR_SHIFT) - lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT - - /* Translate to virtual address in P1 */ - andl r0, 0xf000 - sbr r0, 31 - add r2, r0, r1 << 2 - ld.w r3, r2[0] - sbr r3, _PAGE_BIT_DIRTY - mov r0, r3 - st.w r2[0], r3 - - /* The page table is up-to-date. Update the TLB entry as well */ - andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK) - mtsr SYSREG_TLBELO, r0 - - /* MMUCR[DRP] is updated automatically, so let's go... */ - tlbw - - popm r0-r3 - rete - -do_fpe_ll: - sub sp, 4 - stmts --sp, r0-lr - call save_full_context_ex - unmask_interrupts - mov r12, 26 - mov r11, sp - call do_fpe - rjmp ret_from_exception - -ret_from_exception: - mask_interrupts - lddsp r4, sp[REG_SR] - - andh r4, (MODE_MASK >> 16), COH - brne fault_resume_kernel - - get_thread_info r0 - ld.w r1, r0[TI_flags] - andl r1, _TIF_WORK_MASK, COH - brne fault_exit_work - -fault_resume_user: - popm r8-r9 - mask_exceptions - mtsr SYSREG_RAR_EX, r8 - mtsr SYSREG_RSR_EX, r9 - ldmts sp++, r0-lr - sub sp, -4 - rete - -fault_resume_kernel: -#ifdef CONFIG_PREEMPT - get_thread_info r0 - ld.w r2, r0[TI_preempt_count] - cp.w r2, 0 - brne 1f - ld.w r1, r0[TI_flags] - bld r1, TIF_NEED_RESCHED - brcc 1f - lddsp r4, sp[REG_SR] - bld r4, SYSREG_GM_OFFSET - brcs 1f - call preempt_schedule_irq -1: -#endif - - popm r8-r9 - mask_exceptions - mfsr r1, SYSREG_SR - mtsr SYSREG_RAR_EX, r8 - mtsr SYSREG_RSR_EX, r9 - popm lr - sub sp, -4 /* ignore SP */ - popm r0-r12 - sub sp, -4 /* ignore r12_orig */ - rete - -irq_exit_work: - /* Switch to exception mode so that we can share the same code. */ - mfsr r8, SYSREG_SR - cbr r8, SYSREG_M0_OFFSET - orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2)) - mtsr SYSREG_SR, r8 - sub pc, -2 - get_thread_info r0 - ld.w r1, r0[TI_flags] - -fault_exit_work: - bld r1, TIF_NEED_RESCHED - brcc 1f - unmask_interrupts - call schedule - mask_interrupts - ld.w r1, r0[TI_flags] - rjmp fault_exit_work - -1: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME - tst r1, r2 - breq 2f - unmask_interrupts - mov r12, sp - mov r11, r0 - call do_notify_resume - mask_interrupts - ld.w r1, r0[TI_flags] - rjmp fault_exit_work - -2: bld r1, TIF_BREAKPOINT - brcc fault_resume_user - rjmp enter_monitor_mode - - .section .kprobes.text, "ax", @progbits - .type handle_debug, @function -handle_debug: - sub sp, 4 /* r12_orig */ - stmts --sp, r0-lr - mfsr r8, SYSREG_RAR_DBG - mfsr r9, SYSREG_RSR_DBG - unmask_exceptions - pushm r8-r9 - bfextu r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE - brne debug_fixup_regs - -.Ldebug_fixup_cont: -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off -#endif - mov r12, sp - call do_debug - mov sp, r12 - - lddsp r2, sp[REG_SR] - bfextu r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE - brne debug_resume_kernel - - get_thread_info r0 - ld.w r1, r0[TI_flags] - mov r2, _TIF_DBGWORK_MASK - tst r1, r2 - brne debug_exit_work - - bld r1, TIF_SINGLE_STEP - brcc 1f - mfdr r4, OCD_DC - sbr r4, OCD_DC_SS_BIT - mtdr OCD_DC, r4 - -1: popm r10,r11 - mask_exceptions - mtsr SYSREG_RSR_DBG, r11 - mtsr SYSREG_RAR_DBG, r10 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_on -1: -#endif - ldmts sp++, r0-lr - sub sp, -4 - retd - .size handle_debug, . - handle_debug - - /* Mode of the trapped context is in r9 */ - .type debug_fixup_regs, @function -debug_fixup_regs: - mfsr r8, SYSREG_SR - mov r10, r8 - bfins r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE - mtsr SYSREG_SR, r8 - sub pc, -2 - stdsp sp[REG_LR], lr - mtsr SYSREG_SR, r10 - sub pc, -2 - sub r8, sp, -FRAME_SIZE_FULL - stdsp sp[REG_SP], r8 - rjmp .Ldebug_fixup_cont - .size debug_fixup_regs, . - debug_fixup_regs - - .type debug_resume_kernel, @function -debug_resume_kernel: - mask_exceptions - popm r10, r11 - mtsr SYSREG_RAR_DBG, r10 - mtsr SYSREG_RSR_DBG, r11 -#ifdef CONFIG_TRACE_IRQFLAGS - bld r11, SYSREG_GM_OFFSET - brcc 1f - call trace_hardirqs_on -1: -#endif - mfsr r2, SYSREG_SR - mov r1, r2 - bfins r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE - mtsr SYSREG_SR, r2 - sub pc, -2 - popm lr - mtsr SYSREG_SR, r1 - sub pc, -2 - sub sp, -4 /* skip SP */ - popm r0-r12 - sub sp, -4 - retd - .size debug_resume_kernel, . - debug_resume_kernel - - .type debug_exit_work, @function -debug_exit_work: - /* - * We must return from Monitor Mode using a retd, and we must - * not schedule since that involves the D bit in SR getting - * cleared by something other than the debug hardware. This - * may cause undefined behaviour according to the Architecture - * manual. - * - * So we fix up the return address and status and return to a - * stub below in Exception mode. From there, we can follow the - * normal exception return path. - * - * The real return address and status registers are stored on - * the stack in the way the exception return path understands, - * so no need to fix anything up there. - */ - sub r8, pc, . - fault_exit_work - mtsr SYSREG_RAR_DBG, r8 - mov r9, 0 - orh r9, hi(SR_EM | SR_GM | MODE_EXCEPTION) - mtsr SYSREG_RSR_DBG, r9 - sub pc, -2 - retd - .size debug_exit_work, . - debug_exit_work - - .set rsr_int0, SYSREG_RSR_INT0 - .set rsr_int1, SYSREG_RSR_INT1 - .set rsr_int2, SYSREG_RSR_INT2 - .set rsr_int3, SYSREG_RSR_INT3 - .set rar_int0, SYSREG_RAR_INT0 - .set rar_int1, SYSREG_RAR_INT1 - .set rar_int2, SYSREG_RAR_INT2 - .set rar_int3, SYSREG_RAR_INT3 - - .macro IRQ_LEVEL level - .type irq_level\level, @function -irq_level\level: - sub sp, 4 /* r12_orig */ - stmts --sp,r0-lr - mfsr r8, rar_int\level - mfsr r9, rsr_int\level - -#ifdef CONFIG_PREEMPT - sub r11, pc, (. - system_call) - cp.w r11, r8 - breq 4f -#endif - - pushm r8-r9 - - mov r11, sp - mov r12, \level - - call do_IRQ - - lddsp r4, sp[REG_SR] - bfextu r4, r4, SYSREG_M0_OFFSET, 3 - cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET - breq 2f - cp.w r4, MODE_USER >> SYSREG_M0_OFFSET -#ifdef CONFIG_PREEMPT - brne 3f -#else - brne 1f -#endif - - get_thread_info r0 - ld.w r1, r0[TI_flags] - andl r1, _TIF_WORK_MASK, COH - brne irq_exit_work - -1: -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_on -#endif - popm r8-r9 - mtsr rar_int\level, r8 - mtsr rsr_int\level, r9 - ldmts sp++,r0-lr - sub sp, -4 /* ignore r12_orig */ - rete - -#ifdef CONFIG_PREEMPT -4: mask_interrupts - mfsr r8, rsr_int\level - sbr r8, 16 - mtsr rsr_int\level, r8 - ldmts sp++, r0-lr - sub sp, -4 /* ignore r12_orig */ - rete -#endif - -2: get_thread_info r0 - ld.w r1, r0[TI_flags] - bld r1, TIF_CPU_GOING_TO_SLEEP -#ifdef CONFIG_PREEMPT - brcc 3f -#else - brcc 1b -#endif - sub r1, pc, . - cpu_idle_skip_sleep - stdsp sp[REG_PC], r1 -#ifdef CONFIG_PREEMPT -3: get_thread_info r0 - ld.w r2, r0[TI_preempt_count] - cp.w r2, 0 - brne 1b - ld.w r1, r0[TI_flags] - bld r1, TIF_NEED_RESCHED - brcc 1b - lddsp r4, sp[REG_SR] - bld r4, SYSREG_GM_OFFSET - brcs 1b - call preempt_schedule_irq -#endif - rjmp 1b - .endm - - .section .irq.text,"ax",@progbits - - .global irq_level0 - .global irq_level1 - .global irq_level2 - .global irq_level3 - IRQ_LEVEL 0 - IRQ_LEVEL 1 - IRQ_LEVEL 2 - IRQ_LEVEL 3 - - .section .kprobes.text, "ax", @progbits - .type enter_monitor_mode, @function -enter_monitor_mode: - /* - * We need to enter monitor mode to do a single step. The - * monitor code will alter the return address so that we - * return directly to the user instead of returning here. - */ - breakpoint - rjmp breakpoint_failed - - .size enter_monitor_mode, . - enter_monitor_mode - - .type debug_trampoline, @function - .global debug_trampoline -debug_trampoline: - /* - * Save the registers on the stack so that the monitor code - * can find them easily. - */ - sub sp, 4 /* r12_orig */ - stmts --sp, r0-lr - get_thread_info r0 - ld.w r8, r0[TI_rar_saved] - ld.w r9, r0[TI_rsr_saved] - pushm r8-r9 - - /* - * The monitor code will alter the return address so we don't - * return here. - */ - breakpoint - rjmp breakpoint_failed - .size debug_trampoline, . - debug_trampoline - - .type breakpoint_failed, @function -breakpoint_failed: - /* - * Something went wrong. Perhaps the debug hardware isn't - * enabled? - */ - lda.w r12, msg_breakpoint_failed - mov r11, sp - mov r10, 9 /* SIGKILL */ - call die -1: rjmp 1b - -msg_breakpoint_failed: - .asciz "Failed to enter Debug Mode" diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S deleted file mode 100644 index 59eae6dfbed2..000000000000 --- a/arch/avr32/kernel/head.S +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Non-board-specific low-level startup code - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/page.h> - - .section .init.text,"ax" - .global kernel_entry -kernel_entry: - /* Start the show */ - lddpc pc, kernel_start_addr - - .align 2 -kernel_start_addr: - .long start_kernel diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c deleted file mode 100644 index 900e49b2258b..000000000000 --- a/arch/avr32/kernel/irq.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * Based on arch/i386/kernel/irq.c - * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar - * - * 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/interrupt.h> -#include <linux/irq.h> -#include <linux/kernel_stat.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/device.h> - -/* May be overridden by platform code */ -int __weak nmi_enable(void) -{ - return -ENOSYS; -} - -void __weak nmi_disable(void) -{ - -} diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c deleted file mode 100644 index a94ece4a72c8..000000000000 --- a/arch/avr32/kernel/kprobes.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Kernel Probes (KProbes) - * - * Copyright (C) 2005-2006 Atmel Corporation - * - * Based on arch/ppc64/kernel/kprobes.c - * Copyright (C) IBM Corporation, 2002, 2004 - * - * 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/kprobes.h> -#include <linux/ptrace.h> - -#include <asm/cacheflush.h> -#include <linux/kdebug.h> -#include <asm/ocd.h> - -DEFINE_PER_CPU(struct kprobe *, current_kprobe); -static unsigned long kprobe_status; -static struct pt_regs jprobe_saved_regs; - -struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; - -int __kprobes arch_prepare_kprobe(struct kprobe *p) -{ - int ret = 0; - - if ((unsigned long)p->addr & 0x01) { - printk("Attempt to register kprobe at an unaligned address\n"); - ret = -EINVAL; - } - - /* XXX: Might be a good idea to check if p->addr is a valid - * kernel address as well... */ - - if (!ret) { - pr_debug("copy kprobe at %p\n", p->addr); - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); - p->opcode = *p->addr; - } - - return ret; -} - -void __kprobes arch_arm_kprobe(struct kprobe *p) -{ - pr_debug("arming kprobe at %p\n", p->addr); - ocd_enable(NULL); - *p->addr = BREAKPOINT_INSTRUCTION; - flush_icache_range((unsigned long)p->addr, - (unsigned long)p->addr + sizeof(kprobe_opcode_t)); -} - -void __kprobes arch_disarm_kprobe(struct kprobe *p) -{ - pr_debug("disarming kprobe at %p\n", p->addr); - ocd_disable(NULL); - *p->addr = p->opcode; - flush_icache_range((unsigned long)p->addr, - (unsigned long)p->addr + sizeof(kprobe_opcode_t)); -} - -static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) -{ - unsigned long dc; - - pr_debug("preparing to singlestep over %p (PC=%08lx)\n", - p->addr, regs->pc); - - BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D))); - - dc = ocd_read(DC); - dc |= 1 << OCD_DC_SS_BIT; - ocd_write(DC, dc); - - /* - * We must run the instruction from its original location - * since it may actually reference PC. - * - * TODO: Do the instruction replacement directly in icache. - */ - *p->addr = p->opcode; - flush_icache_range((unsigned long)p->addr, - (unsigned long)p->addr + sizeof(kprobe_opcode_t)); -} - -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) -{ - unsigned long dc; - - pr_debug("resuming execution at PC=%08lx\n", regs->pc); - - dc = ocd_read(DC); - dc &= ~(1 << OCD_DC_SS_BIT); - ocd_write(DC, dc); - - *p->addr = BREAKPOINT_INSTRUCTION; - flush_icache_range((unsigned long)p->addr, - (unsigned long)p->addr + sizeof(kprobe_opcode_t)); -} - -static void __kprobes set_current_kprobe(struct kprobe *p) -{ - __this_cpu_write(current_kprobe, p); -} - -static int __kprobes kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *p; - void *addr = (void *)regs->pc; - int ret = 0; - - pr_debug("kprobe_handler: kprobe_running=%p\n", - kprobe_running()); - - /* - * We don't want to be preempted for the entire - * duration of kprobe processing - */ - preempt_disable(); - - /* Check that we're not recursing */ - if (kprobe_running()) { - p = get_kprobe(addr); - if (p) { - if (kprobe_status == KPROBE_HIT_SS) { - printk("FIXME: kprobe hit while single-stepping!\n"); - goto no_kprobe; - } - - printk("FIXME: kprobe hit while handling another kprobe\n"); - goto no_kprobe; - } else { - p = kprobe_running(); - if (p->break_handler && p->break_handler(p, regs)) - goto ss_probe; - } - /* If it's not ours, can't be delete race, (we hold lock). */ - goto no_kprobe; - } - - p = get_kprobe(addr); - if (!p) - goto no_kprobe; - - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p); - if (p->pre_handler && p->pre_handler(p, regs)) - /* handler has already set things up, so skip ss setup */ - return 1; - -ss_probe: - prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; - return 1; - -no_kprobe: - preempt_enable_no_resched(); - return ret; -} - -static int __kprobes post_kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *cur = kprobe_running(); - - pr_debug("post_kprobe_handler, cur=%p\n", cur); - - if (!cur) - return 0; - - if (cur->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - cur->post_handler(cur, regs, 0); - } - - resume_execution(cur, regs); - reset_current_kprobe(); - preempt_enable_no_resched(); - - return 1; -} - -int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) -{ - struct kprobe *cur = kprobe_running(); - - pr_debug("kprobe_fault_handler: trapnr=%d\n", trapnr); - - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) - return 1; - - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(cur, regs); - preempt_enable_no_resched(); - } - return 0; -} - -/* - * Wrapper routine to for handling exceptions. - */ -int __kprobes kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct die_args *args = (struct die_args *)data; - int ret = NOTIFY_DONE; - - pr_debug("kprobe_exceptions_notify: val=%lu, data=%p\n", - val, data); - - switch (val) { - case DIE_BREAKPOINT: - if (kprobe_handler(args->regs)) - ret = NOTIFY_STOP; - break; - case DIE_SSTEP: - if (post_kprobe_handler(args->regs)) - ret = NOTIFY_STOP; - break; - default: - break; - } - - return ret; -} - -int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct jprobe *jp = container_of(p, struct jprobe, kp); - - memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs)); - - /* - * TODO: We should probably save some of the stack here as - * well, since gcc may pass arguments on the stack for certain - * functions (lots of arguments, large aggregates, varargs) - */ - - /* setup return addr to the jprobe handler routine */ - regs->pc = (unsigned long)jp->entry; - return 1; -} - -void __kprobes jprobe_return(void) -{ - asm volatile("breakpoint" ::: "memory"); -} - -int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) -{ - /* - * FIXME - we should ideally be validating that we got here 'cos - * of the "trap" in jprobe_return() above, before restoring the - * saved regs... - */ - memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs)); - return 1; -} - -int __init arch_init_kprobes(void) -{ - /* TODO: Register kretprobe trampoline */ - return 0; -} diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c deleted file mode 100644 index 2b4c54c04cb6..000000000000 --- a/arch/avr32/kernel/module.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * AVR32-specific kernel module loader - * - * Copyright (C) 2005-2006 Atmel Corporation - * - * GOT initialization parts are based on the s390 version - * Copyright (C) 2002, 2003 IBM Deutschland Entwicklung GmbH, - * IBM Corporation - * - * 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/bug.h> -#include <linux/elf.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/moduleloader.h> -#include <linux/vmalloc.h> - -void module_arch_freeing_init(struct module *mod) -{ - vfree(mod->arch.syminfo); - mod->arch.syminfo = NULL; -} - -static inline int check_rela(Elf32_Rela *rela, struct module *module, - char *strings, Elf32_Sym *symbols) -{ - struct mod_arch_syminfo *info; - - info = module->arch.syminfo + ELF32_R_SYM(rela->r_info); - switch (ELF32_R_TYPE(rela->r_info)) { - case R_AVR32_GOT32: - case R_AVR32_GOT16: - case R_AVR32_GOT8: - case R_AVR32_GOT21S: - case R_AVR32_GOT18SW: /* mcall */ - case R_AVR32_GOT16S: /* ld.w */ - if (rela->r_addend != 0) { - printk(KERN_ERR - "GOT relocation against %s at offset %u with addend\n", - strings + symbols[ELF32_R_SYM(rela->r_info)].st_name, - rela->r_offset); - return -ENOEXEC; - } - if (info->got_offset == -1UL) { - info->got_offset = module->arch.got_size; - module->arch.got_size += sizeof(void *); - } - pr_debug("GOT[%3lu] %s\n", info->got_offset, - strings + symbols[ELF32_R_SYM(rela->r_info)].st_name); - break; - } - - return 0; -} - -int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, - char *secstrings, struct module *module) -{ - Elf32_Shdr *symtab; - Elf32_Sym *symbols; - Elf32_Rela *rela; - char *strings; - int nrela, i, j; - int ret; - - /* Find the symbol table */ - symtab = NULL; - for (i = 0; i < hdr->e_shnum; i++) - switch (sechdrs[i].sh_type) { - case SHT_SYMTAB: - symtab = &sechdrs[i]; - break; - } - if (!symtab) { - printk(KERN_ERR "module %s: no symbol table\n", module->name); - return -ENOEXEC; - } - - /* Allocate room for one syminfo structure per symbol. */ - module->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym); - module->arch.syminfo = vmalloc(module->arch.nsyms - * sizeof(struct mod_arch_syminfo)); - if (!module->arch.syminfo) - return -ENOMEM; - - symbols = (void *)hdr + symtab->sh_offset; - strings = (void *)hdr + sechdrs[symtab->sh_link].sh_offset; - for (i = 0; i < module->arch.nsyms; i++) { - if (symbols[i].st_shndx == SHN_UNDEF && - strcmp(strings + symbols[i].st_name, - "_GLOBAL_OFFSET_TABLE_") == 0) - /* "Define" it as absolute. */ - symbols[i].st_shndx = SHN_ABS; - module->arch.syminfo[i].got_offset = -1UL; - module->arch.syminfo[i].got_initialized = 0; - } - - /* Allocate GOT entries for symbols that need it. */ - module->arch.got_size = 0; - for (i = 0; i < hdr->e_shnum; i++) { - if (sechdrs[i].sh_type != SHT_RELA) - continue; - nrela = sechdrs[i].sh_size / sizeof(Elf32_Rela); - rela = (void *)hdr + sechdrs[i].sh_offset; - for (j = 0; j < nrela; j++) { - ret = check_rela(rela + j, module, - strings, symbols); - if (ret) - goto out_free_syminfo; - } - } - - /* - * Increase core size to make room for GOT and set start - * offset for GOT. - */ - module->core_layout.size = ALIGN(module->core_layout.size, 4); - module->arch.got_offset = module->core_layout.size; - module->core_layout.size += module->arch.got_size; - - return 0; - -out_free_syminfo: - vfree(module->arch.syminfo); - module->arch.syminfo = NULL; - - return ret; -} - -static inline int reloc_overflow(struct module *module, const char *reloc_name, - Elf32_Addr relocation) -{ - printk(KERN_ERR "module %s: Value %lx does not fit relocation %s\n", - module->name, (unsigned long)relocation, reloc_name); - return -ENOEXEC; -} - -#define get_u16(loc) (*((uint16_t *)loc)) -#define put_u16(loc, val) (*((uint16_t *)loc) = (val)) - -int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, - unsigned int symindex, unsigned int relindex, - struct module *module) -{ - Elf32_Shdr *symsec = sechdrs + symindex; - Elf32_Shdr *relsec = sechdrs + relindex; - Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; - Elf32_Rela *rel = (void *)relsec->sh_addr; - unsigned int i; - int ret = 0; - - for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) { - struct mod_arch_syminfo *info; - Elf32_Sym *sym; - Elf32_Addr relocation; - uint32_t *location; - uint32_t value; - - location = (void *)dstsec->sh_addr + rel->r_offset; - sym = (Elf32_Sym *)symsec->sh_addr + ELF32_R_SYM(rel->r_info); - relocation = sym->st_value + rel->r_addend; - - info = module->arch.syminfo + ELF32_R_SYM(rel->r_info); - - /* Initialize GOT entry if necessary */ - switch (ELF32_R_TYPE(rel->r_info)) { - case R_AVR32_GOT32: - case R_AVR32_GOT16: - case R_AVR32_GOT8: - case R_AVR32_GOT21S: - case R_AVR32_GOT18SW: - case R_AVR32_GOT16S: - if (!info->got_initialized) { - Elf32_Addr *gotent; - - gotent = (module->core_layout.base - + module->arch.got_offset - + info->got_offset); - *gotent = relocation; - info->got_initialized = 1; - } - - relocation = info->got_offset; - break; - } - - switch (ELF32_R_TYPE(rel->r_info)) { - case R_AVR32_32: - case R_AVR32_32_CPENT: - *location = relocation; - break; - case R_AVR32_22H_PCREL: - relocation -= (Elf32_Addr)location; - if ((relocation & 0xffe00001) != 0 - && (relocation & 0xffc00001) != 0xffc00000) - return reloc_overflow(module, - "R_AVR32_22H_PCREL", - relocation); - relocation >>= 1; - - value = *location; - value = ((value & 0xe1ef0000) - | (relocation & 0xffff) - | ((relocation & 0x10000) << 4) - | ((relocation & 0x1e0000) << 8)); - *location = value; - break; - case R_AVR32_11H_PCREL: - relocation -= (Elf32_Addr)location; - if ((relocation & 0xfffffc01) != 0 - && (relocation & 0xfffff801) != 0xfffff800) - return reloc_overflow(module, - "R_AVR32_11H_PCREL", - relocation); - value = get_u16(location); - value = ((value & 0xf00c) - | ((relocation & 0x1fe) << 3) - | ((relocation & 0x600) >> 9)); - put_u16(location, value); - break; - case R_AVR32_9H_PCREL: - relocation -= (Elf32_Addr)location; - if ((relocation & 0xffffff01) != 0 - && (relocation & 0xfffffe01) != 0xfffffe00) - return reloc_overflow(module, - "R_AVR32_9H_PCREL", - relocation); - value = get_u16(location); - value = ((value & 0xf00f) - | ((relocation & 0x1fe) << 3)); - put_u16(location, value); - break; - case R_AVR32_9UW_PCREL: - relocation -= ((Elf32_Addr)location) & 0xfffffffc; - if ((relocation & 0xfffffc03) != 0) - return reloc_overflow(module, - "R_AVR32_9UW_PCREL", - relocation); - value = get_u16(location); - value = ((value & 0xf80f) - | ((relocation & 0x1fc) << 2)); - put_u16(location, value); - break; - case R_AVR32_GOTPC: - /* - * R6 = PC - (PC - GOT) - * - * At this point, relocation contains the - * value of PC. Just subtract the value of - * GOT, and we're done. - */ - pr_debug("GOTPC: PC=0x%x, got_offset=0x%lx, core=0x%p\n", - relocation, module->arch.got_offset, - module->core_layout.base); - relocation -= ((unsigned long)module->core_layout.base - + module->arch.got_offset); - *location = relocation; - break; - case R_AVR32_GOT18SW: - if ((relocation & 0xfffe0003) != 0 - && (relocation & 0xfffc0000) != 0xfffc0000) - return reloc_overflow(module, "R_AVR32_GOT18SW", - relocation); - relocation >>= 2; - /* fall through */ - case R_AVR32_GOT16S: - if ((relocation & 0xffff8000) != 0 - && (relocation & 0xffff0000) != 0xffff0000) - return reloc_overflow(module, "R_AVR32_GOT16S", - relocation); - pr_debug("GOT reloc @ 0x%x -> %u\n", - rel->r_offset, relocation); - value = *location; - value = ((value & 0xffff0000) - | (relocation & 0xffff)); - *location = value; - break; - - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - module->name, ELF32_R_TYPE(rel->r_info)); - return -ENOEXEC; - } - } - - return ret; -} diff --git a/arch/avr32/kernel/nmi_debug.c b/arch/avr32/kernel/nmi_debug.c deleted file mode 100644 index 25823049bb99..000000000000 --- a/arch/avr32/kernel/nmi_debug.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007 Atmel Corporation - * - * 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/delay.h> -#include <linux/kdebug.h> -#include <linux/notifier.h> -#include <linux/sched.h> -#include <linux/sched/debug.h> - -#include <asm/irq.h> - -enum nmi_action { - NMI_SHOW_STATE = 1 << 0, - NMI_SHOW_REGS = 1 << 1, - NMI_DIE = 1 << 2, - NMI_DEBOUNCE = 1 << 3, -}; - -static unsigned long nmi_actions; - -static int nmi_debug_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct die_args *args = data; - - if (likely(val != DIE_NMI)) - return NOTIFY_DONE; - - if (nmi_actions & NMI_SHOW_STATE) - show_state(); - if (nmi_actions & NMI_SHOW_REGS) - show_regs(args->regs); - if (nmi_actions & NMI_DEBOUNCE) - mdelay(10); - if (nmi_actions & NMI_DIE) - return NOTIFY_BAD; - - return NOTIFY_OK; -} - -static struct notifier_block nmi_debug_nb = { - .notifier_call = nmi_debug_notify, -}; - -static int __init nmi_debug_setup(char *str) -{ - char *p, *sep; - - register_die_notifier(&nmi_debug_nb); - if (nmi_enable()) { - printk(KERN_WARNING "Unable to enable NMI.\n"); - return 0; - } - - if (*str != '=') - return 0; - - for (p = str + 1; *p; p = sep + 1) { - sep = strchr(p, ','); - if (sep) - *sep = 0; - if (strcmp(p, "state") == 0) - nmi_actions |= NMI_SHOW_STATE; - else if (strcmp(p, "regs") == 0) - nmi_actions |= NMI_SHOW_REGS; - else if (strcmp(p, "debounce") == 0) - nmi_actions |= NMI_DEBOUNCE; - else if (strcmp(p, "die") == 0) - nmi_actions |= NMI_DIE; - else - printk(KERN_WARNING "NMI: Unrecognized action `%s'\n", - p); - if (!sep) - break; - } - - return 0; -} -__setup("nmi_debug", nmi_debug_setup); diff --git a/arch/avr32/kernel/ocd.c b/arch/avr32/kernel/ocd.c deleted file mode 100644 index 1b0245d4e0ca..000000000000 --- a/arch/avr32/kernel/ocd.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2007 Atmel Corporation - * - * 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/init.h> -#include <linux/sched.h> -#include <linux/spinlock.h> - -#include <asm/ocd.h> - -static long ocd_count; -static spinlock_t ocd_lock; - -/** - * ocd_enable - enable on-chip debugging - * @child: task to be debugged - * - * If @child is non-NULL, ocd_enable() first checks if debugging has - * already been enabled for @child, and if it has, does nothing. - * - * If @child is NULL (e.g. when debugging the kernel), or debugging - * has not already been enabled for it, ocd_enable() increments the - * reference count and enables the debugging hardware. - */ -void ocd_enable(struct task_struct *child) -{ - u32 dc; - - if (child) - pr_debug("ocd_enable: child=%s [%u]\n", - child->comm, child->pid); - else - pr_debug("ocd_enable (no child)\n"); - - if (!child || !test_and_set_tsk_thread_flag(child, TIF_DEBUG)) { - spin_lock(&ocd_lock); - ocd_count++; - dc = ocd_read(DC); - dc |= (1 << OCD_DC_MM_BIT) | (1 << OCD_DC_DBE_BIT); - ocd_write(DC, dc); - spin_unlock(&ocd_lock); - } -} - -/** - * ocd_disable - disable on-chip debugging - * @child: task that was being debugged, but isn't anymore - * - * If @child is non-NULL, ocd_disable() checks if debugging is enabled - * for @child, and if it isn't, does nothing. - * - * If @child is NULL (e.g. when debugging the kernel), or debugging is - * enabled, ocd_disable() decrements the reference count, and if it - * reaches zero, disables the debugging hardware. - */ -void ocd_disable(struct task_struct *child) -{ - u32 dc; - - if (!child) - pr_debug("ocd_disable (no child)\n"); - else if (test_tsk_thread_flag(child, TIF_DEBUG)) - pr_debug("ocd_disable: child=%s [%u]\n", - child->comm, child->pid); - - if (!child || test_and_clear_tsk_thread_flag(child, TIF_DEBUG)) { - spin_lock(&ocd_lock); - ocd_count--; - - WARN_ON(ocd_count < 0); - - if (ocd_count <= 0) { - dc = ocd_read(DC); - dc &= ~((1 << OCD_DC_MM_BIT) | (1 << OCD_DC_DBE_BIT)); - ocd_write(DC, dc); - } - spin_unlock(&ocd_lock); - } -} - -#ifdef CONFIG_DEBUG_FS -#include <linux/debugfs.h> -#include <linux/module.h> - -static struct dentry *ocd_debugfs_root; -static struct dentry *ocd_debugfs_DC; -static struct dentry *ocd_debugfs_DS; -static struct dentry *ocd_debugfs_count; - -static int ocd_DC_get(void *data, u64 *val) -{ - *val = ocd_read(DC); - return 0; -} -static int ocd_DC_set(void *data, u64 val) -{ - ocd_write(DC, val); - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_DC, ocd_DC_get, ocd_DC_set, "0x%08llx\n"); - -static int ocd_DS_get(void *data, u64 *val) -{ - *val = ocd_read(DS); - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_DS, ocd_DS_get, NULL, "0x%08llx\n"); - -static int ocd_count_get(void *data, u64 *val) -{ - *val = ocd_count; - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_count, ocd_count_get, NULL, "%lld\n"); - -static void ocd_debugfs_init(void) -{ - struct dentry *root; - - root = debugfs_create_dir("ocd", NULL); - if (IS_ERR(root) || !root) - goto err_root; - ocd_debugfs_root = root; - - ocd_debugfs_DC = debugfs_create_file("DC", S_IRUSR | S_IWUSR, - root, NULL, &fops_DC); - if (!ocd_debugfs_DC) - goto err_DC; - - ocd_debugfs_DS = debugfs_create_file("DS", S_IRUSR, root, - NULL, &fops_DS); - if (!ocd_debugfs_DS) - goto err_DS; - - ocd_debugfs_count = debugfs_create_file("count", S_IRUSR, root, - NULL, &fops_count); - if (!ocd_debugfs_count) - goto err_count; - - return; - -err_count: - debugfs_remove(ocd_debugfs_DS); -err_DS: - debugfs_remove(ocd_debugfs_DC); -err_DC: - debugfs_remove(ocd_debugfs_root); -err_root: - printk(KERN_WARNING "OCD: Failed to create debugfs entries\n"); -} -#else -static inline void ocd_debugfs_init(void) -{ - -} -#endif - -static int __init ocd_init(void) -{ - spin_lock_init(&ocd_lock); - ocd_debugfs_init(); - return 0; -} -arch_initcall(ocd_init); diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c deleted file mode 100644 index ad0dfccedb79..000000000000 --- a/arch/avr32/kernel/process.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/sched.h> -#include <linux/sched/debug.h> -#include <linux/sched/task.h> -#include <linux/sched/task_stack.h> -#include <linux/module.h> -#include <linux/kallsyms.h> -#include <linux/fs.h> -#include <linux/pm.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/reboot.h> -#include <linux/tick.h> -#include <linux/uaccess.h> -#include <linux/unistd.h> - -#include <asm/sysreg.h> -#include <asm/ocd.h> -#include <asm/syscalls.h> - -#include <mach/pm.h> - -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -/* - * This file handles the architecture-dependent parts of process handling.. - */ - -void arch_cpu_idle(void) -{ - cpu_enter_idle(); -} - -void machine_halt(void) -{ - /* - * Enter Stop mode. The 32 kHz oscillator will keep running so - * the RTC will keep the time properly and the system will - * boot quickly. - */ - asm volatile("sleep 3\n\t" - "sub pc, -2"); -} - -void machine_power_off(void) -{ - if (pm_power_off) - pm_power_off(); -} - -void machine_restart(char *cmd) -{ - ocd_write(DC, (1 << OCD_DC_DBE_BIT)); - ocd_write(DC, (1 << OCD_DC_RES_BIT)); - while (1) ; -} - -/* - * Free current thread data structures etc - */ -void exit_thread(struct task_struct *tsk) -{ - ocd_disable(tsk); -} - -void flush_thread(void) -{ - /* nothing to do */ -} - -void release_thread(struct task_struct *dead_task) -{ - /* do nothing */ -} - -static void dump_mem(const char *str, const char *log_lvl, - unsigned long bottom, unsigned long top) -{ - unsigned long p; - int i; - - printk("%s%s(0x%08lx to 0x%08lx)\n", log_lvl, str, bottom, top); - - for (p = bottom & ~31; p < top; ) { - printk("%s%04lx: ", log_lvl, p & 0xffff); - - for (i = 0; i < 8; i++, p += 4) { - unsigned int val; - - if (p < bottom || p >= top) - printk(" "); - else { - if (__get_user(val, (unsigned int __user *)p)) { - printk("\n"); - goto out; - } - printk("%08x ", val); - } - } - printk("\n"); - } - -out: - return; -} - -static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) -{ - return (p > (unsigned long)tinfo) - && (p < (unsigned long)tinfo + THREAD_SIZE - 3); -} - -#ifdef CONFIG_FRAME_POINTER -static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs, const char *log_lvl) -{ - unsigned long lr, fp; - struct thread_info *tinfo; - - if (regs) - fp = regs->r7; - else if (tsk == current) - asm("mov %0, r7" : "=r"(fp)); - else - fp = tsk->thread.cpu_context.r7; - - /* - * Walk the stack as long as the frame pointer (a) is within - * the kernel stack of the task, and (b) it doesn't move - * downwards. - */ - tinfo = task_thread_info(tsk); - printk("%sCall trace:\n", log_lvl); - while (valid_stack_ptr(tinfo, fp)) { - unsigned long new_fp; - - lr = *(unsigned long *)fp; -#ifdef CONFIG_KALLSYMS - printk("%s [<%08lx>] ", log_lvl, lr); -#else - printk(" [<%08lx>] ", lr); -#endif - print_symbol("%s\n", lr); - - new_fp = *(unsigned long *)(fp + 4); - if (new_fp <= fp) - break; - fp = new_fp; - } - printk("\n"); -} -#else -static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs, const char *log_lvl) -{ - unsigned long addr; - - printk("%sCall trace:\n", log_lvl); - - while (!kstack_end(sp)) { - addr = *sp++; - if (kernel_text_address(addr)) { -#ifdef CONFIG_KALLSYMS - printk("%s [<%08lx>] ", log_lvl, addr); -#else - printk(" [<%08lx>] ", addr); -#endif - print_symbol("%s\n", addr); - } - } - printk("\n"); -} -#endif - -void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp, - struct pt_regs *regs, const char *log_lvl) -{ - struct thread_info *tinfo; - - if (sp == 0) { - if (tsk) - sp = tsk->thread.cpu_context.ksp; - else - sp = (unsigned long)&tinfo; - } - if (!tsk) - tsk = current; - - tinfo = task_thread_info(tsk); - - if (valid_stack_ptr(tinfo, sp)) { - dump_mem("Stack: ", log_lvl, sp, - THREAD_SIZE + (unsigned long)tinfo); - show_trace_log_lvl(tsk, (unsigned long *)sp, regs, log_lvl); - } -} - -void show_stack(struct task_struct *tsk, unsigned long *stack) -{ - show_stack_log_lvl(tsk, (unsigned long)stack, NULL, ""); -} - -static const char *cpu_modes[] = { - "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", - "Interrupt level 2", "Interrupt level 3", "Exception", "NMI" -}; - -void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl) -{ - unsigned long sp = regs->sp; - unsigned long lr = regs->lr; - unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT; - - show_regs_print_info(log_lvl); - - if (!user_mode(regs)) { - sp = (unsigned long)regs + FRAME_SIZE_FULL; - - printk("%s", log_lvl); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - printk("%s", log_lvl); - print_symbol("LR is at %s\n", lr); - } - - printk("%spc : [<%08lx>] lr : [<%08lx>] %s\n" - "%ssp : %08lx r12: %08lx r11: %08lx\n", - log_lvl, instruction_pointer(regs), lr, print_tainted(), - log_lvl, sp, regs->r12, regs->r11); - printk("%sr10: %08lx r9 : %08lx r8 : %08lx\n", - log_lvl, regs->r10, regs->r9, regs->r8); - printk("%sr7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", - log_lvl, regs->r7, regs->r6, regs->r5, regs->r4); - printk("%sr3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", - log_lvl, regs->r3, regs->r2, regs->r1, regs->r0); - printk("%sFlags: %c%c%c%c%c\n", log_lvl, - regs->sr & SR_Q ? 'Q' : 'q', - regs->sr & SR_V ? 'V' : 'v', - regs->sr & SR_N ? 'N' : 'n', - regs->sr & SR_Z ? 'Z' : 'z', - regs->sr & SR_C ? 'C' : 'c'); - printk("%sMode bits: %c%c%c%c%c%c%c%c%c%c\n", log_lvl, - regs->sr & SR_H ? 'H' : 'h', - regs->sr & SR_J ? 'J' : 'j', - regs->sr & SR_DM ? 'M' : 'm', - regs->sr & SR_D ? 'D' : 'd', - regs->sr & SR_EM ? 'E' : 'e', - regs->sr & SR_I3M ? '3' : '.', - regs->sr & SR_I2M ? '2' : '.', - regs->sr & SR_I1M ? '1' : '.', - regs->sr & SR_I0M ? '0' : '.', - regs->sr & SR_GM ? 'G' : 'g'); - printk("%sCPU Mode: %s\n", log_lvl, cpu_modes[mode]); -} - -void show_regs(struct pt_regs *regs) -{ - unsigned long sp = regs->sp; - - if (!user_mode(regs)) - sp = (unsigned long)regs + FRAME_SIZE_FULL; - - show_regs_log_lvl(regs, ""); - show_trace_log_lvl(current, (unsigned long *)sp, regs, ""); -} -EXPORT_SYMBOL(show_regs); - -/* Fill in the fpu structure for a core dump. This is easy -- we don't have any */ -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -{ - /* Not valid */ - return 0; -} - -asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); -asmlinkage void syscall_return(void); - -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p) -{ - struct pt_regs *childregs = task_pt_regs(p); - - if (unlikely(p->flags & PF_KTHREAD)) { - memset(childregs, 0, sizeof(struct pt_regs)); - p->thread.cpu_context.r0 = arg; - p->thread.cpu_context.r1 = usp; /* fn */ - p->thread.cpu_context.r2 = (unsigned long)syscall_return; - p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread; - childregs->sr = MODE_SUPERVISOR; - } else { - *childregs = *current_pt_regs(); - if (usp) - childregs->sp = usp; - childregs->r12 = 0; /* Set return value for child */ - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; - } - - p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; - p->thread.cpu_context.ksp = (unsigned long)childregs; - - clear_tsk_thread_flag(p, TIF_DEBUG); - if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) - ocd_enable(p); - - return 0; -} - -/* - * This function is supposed to answer the question "who called - * schedule()?" - */ -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long pc; - unsigned long stack_page; - - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - stack_page = (unsigned long)task_stack_page(p); - BUG_ON(!stack_page); - - /* - * The stored value of PC is either the address right after - * the call to __switch_to() or ret_from_fork. - */ - pc = thread_saved_pc(p); - if (in_sched_functions(pc)) { -#ifdef CONFIG_FRAME_POINTER - unsigned long fp = p->thread.cpu_context.r7; - BUG_ON(fp < stack_page || fp > (THREAD_SIZE + stack_page)); - pc = *(unsigned long *)fp; -#else - /* - * We depend on the frame size of schedule here, which - * is actually quite ugly. It might be possible to - * determine the frame size automatically at build - * time by doing this: - * - compile sched/core.c - * - disassemble the resulting sched.o - * - look for 'sub sp,??' shortly after '<schedule>:' - */ - unsigned long sp = p->thread.cpu_context.ksp + 16; - BUG_ON(sp < stack_page || sp > (THREAD_SIZE + stack_page)); - pc = *(unsigned long *)sp; -#endif - } - - return pc; -} diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c deleted file mode 100644 index 41a14e96a1db..000000000000 --- a/arch/avr32/kernel/ptrace.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ -#undef DEBUG -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/user.h> -#include <linux/security.h> -#include <linux/unistd.h> -#include <linux/notifier.h> - -#include <asm/traps.h> -#include <linux/uaccess.h> -#include <asm/ocd.h> -#include <asm/mmu_context.h> -#include <linux/kdebug.h> - -static struct pt_regs *get_user_regs(struct task_struct *tsk) -{ - return (struct pt_regs *)((unsigned long)task_stack_page(tsk) + - THREAD_SIZE - sizeof(struct pt_regs)); -} - -void user_enable_single_step(struct task_struct *tsk) -{ - pr_debug("user_enable_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", - tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr); - - /* - * We can't schedule in Debug mode, so when TIF_BREAKPOINT is - * set, the system call or exception handler will do a - * breakpoint to enter monitor mode before returning to - * userspace. - * - * The monitor code will then notice that TIF_SINGLE_STEP is - * set and return to userspace with single stepping enabled. - * The CPU will then enter monitor mode again after exactly - * one instruction has been executed, and the monitor code - * will then send a SIGTRAP to the process. - */ - set_tsk_thread_flag(tsk, TIF_BREAKPOINT); - set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); -} - -void user_disable_single_step(struct task_struct *child) -{ - /* XXX(hch): a no-op here seems wrong.. */ -} - -/* - * Called by kernel/ptrace.c when detaching - * - * Make sure any single step bits, etc. are not set - */ -void ptrace_disable(struct task_struct *child) -{ - clear_tsk_thread_flag(child, TIF_SINGLE_STEP); - clear_tsk_thread_flag(child, TIF_BREAKPOINT); - ocd_disable(child); -} - -/* - * Read the word at offset "offset" into the task's "struct user". We - * actually access the pt_regs struct stored on the kernel stack. - */ -static int ptrace_read_user(struct task_struct *tsk, unsigned long offset, - unsigned long __user *data) -{ - unsigned long *regs; - unsigned long value; - - if (offset & 3 || offset >= sizeof(struct user)) { - printk("ptrace_read_user: invalid offset 0x%08lx\n", offset); - return -EIO; - } - - regs = (unsigned long *)get_user_regs(tsk); - - value = 0; - if (offset < sizeof(struct pt_regs)) - value = regs[offset / sizeof(regs[0])]; - - pr_debug("ptrace_read_user(%s[%u], %#lx, %p) -> %#lx\n", - tsk->comm, tsk->pid, offset, data, value); - - return put_user(value, data); -} - -/* - * Write the word "value" to offset "offset" into the task's "struct - * user". We actually access the pt_regs struct stored on the kernel - * stack. - */ -static int ptrace_write_user(struct task_struct *tsk, unsigned long offset, - unsigned long value) -{ - unsigned long *regs; - - pr_debug("ptrace_write_user(%s[%u], %#lx, %#lx)\n", - tsk->comm, tsk->pid, offset, value); - - if (offset & 3 || offset >= sizeof(struct user)) { - pr_debug(" invalid offset 0x%08lx\n", offset); - return -EIO; - } - - if (offset >= sizeof(struct pt_regs)) - return 0; - - regs = (unsigned long *)get_user_regs(tsk); - regs[offset / sizeof(regs[0])] = value; - - return 0; -} - -static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) -{ - struct pt_regs *regs = get_user_regs(tsk); - - return copy_to_user(uregs, regs, sizeof(*regs)) ? -EFAULT : 0; -} - -static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs) -{ - struct pt_regs newregs; - int ret; - - ret = -EFAULT; - if (copy_from_user(&newregs, uregs, sizeof(newregs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); - - ret = -EINVAL; - if (valid_user_regs(&newregs)) { - *regs = newregs; - ret = 0; - } - } - - return ret; -} - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - void __user *datap = (void __user *) data; - - switch (request) { - /* Read the word at location addr in the child process */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - - case PTRACE_PEEKUSR: - ret = ptrace_read_user(child, addr, datap); - break; - - /* Write the word in data at location addr */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - - case PTRACE_POKEUSR: - ret = ptrace_write_user(child, addr, data); - break; - - case PTRACE_GETREGS: - ret = ptrace_getregs(child, datap); - break; - - case PTRACE_SETREGS: - ret = ptrace_setregs(child, datap); - break; - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} - -asmlinkage void syscall_trace(void) -{ - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - if (!(current->ptrace & PT_PTRACED)) - return; - - /* The 0x80 provides a way for the tracing parent to - * distinguish between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - - /* - * this isn't the same as continuing with a signal, but it - * will do for normal use. strace only continues with a - * signal if the stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - pr_debug("syscall_trace: sending signal %d to PID %u\n", - current->exit_code, current->pid); - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} - -/* - * debug_trampoline() is an assembly stub which will store all user - * registers on the stack and execute a breakpoint instruction. - * - * If we single-step into an exception handler which runs with - * interrupts disabled the whole time so it doesn't have to check for - * pending work, its return address will be modified so that it ends - * up returning to debug_trampoline. - * - * If the exception handler decides to store the user context and - * enable interrupts after all, it will restore the original return - * address and status register value. Before it returns, it will - * notice that TIF_BREAKPOINT is set and execute a breakpoint - * instruction. - */ -extern void debug_trampoline(void); - -asmlinkage struct pt_regs *do_debug(struct pt_regs *regs) -{ - struct thread_info *ti; - unsigned long trampoline_addr; - u32 status; - u32 ctrl; - int code; - - status = ocd_read(DS); - ti = current_thread_info(); - code = TRAP_BRKPT; - - pr_debug("do_debug: status=0x%08x PC=0x%08lx SR=0x%08lx tif=0x%08lx\n", - status, regs->pc, regs->sr, ti->flags); - - if (!user_mode(regs)) { - unsigned long die_val = DIE_BREAKPOINT; - - if (status & (1 << OCD_DS_SSS_BIT)) - die_val = DIE_SSTEP; - - if (notify_die(die_val, "ptrace", regs, 0, 0, SIGTRAP) - == NOTIFY_STOP) - return regs; - - if ((status & (1 << OCD_DS_SWB_BIT)) - && test_and_clear_ti_thread_flag( - ti, TIF_BREAKPOINT)) { - /* - * Explicit breakpoint from trampoline or - * exception/syscall/interrupt handler. - * - * The real saved regs are on the stack right - * after the ones we saved on entry. - */ - regs++; - pr_debug(" -> TIF_BREAKPOINT done, adjusted regs:" - "PC=0x%08lx SR=0x%08lx\n", - regs->pc, regs->sr); - BUG_ON(!user_mode(regs)); - - if (test_thread_flag(TIF_SINGLE_STEP)) { - pr_debug("Going to do single step...\n"); - return regs; - } - - /* - * No TIF_SINGLE_STEP means we're done - * stepping over a syscall. Do the trap now. - */ - code = TRAP_TRACE; - } else if ((status & (1 << OCD_DS_SSS_BIT)) - && test_ti_thread_flag(ti, TIF_SINGLE_STEP)) { - - pr_debug("Stepped into something, " - "setting TIF_BREAKPOINT...\n"); - set_ti_thread_flag(ti, TIF_BREAKPOINT); - - /* - * We stepped into an exception, interrupt or - * syscall handler. Some exception handlers - * don't check for pending work, so we need to - * set up a trampoline just in case. - * - * The exception entry code will undo the - * trampoline stuff if it does a full context - * save (which also means that it'll check for - * pending work later.) - */ - if ((regs->sr & MODE_MASK) == MODE_EXCEPTION) { - trampoline_addr - = (unsigned long)&debug_trampoline; - - pr_debug("Setting up trampoline...\n"); - ti->rar_saved = sysreg_read(RAR_EX); - ti->rsr_saved = sysreg_read(RSR_EX); - sysreg_write(RAR_EX, trampoline_addr); - sysreg_write(RSR_EX, (MODE_EXCEPTION - | SR_EM | SR_GM)); - BUG_ON(ti->rsr_saved & MODE_MASK); - } - - /* - * If we stepped into a system call, we - * shouldn't do a single step after we return - * since the return address is right after the - * "scall" instruction we were told to step - * over. - */ - if ((regs->sr & MODE_MASK) == MODE_SUPERVISOR) { - pr_debug("Supervisor; no single step\n"); - clear_ti_thread_flag(ti, TIF_SINGLE_STEP); - } - - ctrl = ocd_read(DC); - ctrl &= ~(1 << OCD_DC_SS_BIT); - ocd_write(DC, ctrl); - - return regs; - } else { - printk(KERN_ERR "Unexpected OCD_DS value: 0x%08x\n", - status); - printk(KERN_ERR "Thread flags: 0x%08lx\n", ti->flags); - die("Unhandled debug trap in kernel mode", - regs, SIGTRAP); - } - } else if (status & (1 << OCD_DS_SSS_BIT)) { - /* Single step in user mode */ - code = TRAP_TRACE; - - ctrl = ocd_read(DC); - ctrl &= ~(1 << OCD_DC_SS_BIT); - ocd_write(DC, ctrl); - } - - pr_debug("Sending SIGTRAP: code=%d PC=0x%08lx SR=0x%08lx\n", - code, regs->pc, regs->sr); - - clear_thread_flag(TIF_SINGLE_STEP); - _exception(SIGTRAP, regs, code, instruction_pointer(regs)); - - return regs; -} diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c deleted file mode 100644 index e6928896da2a..000000000000 --- a/arch/avr32/kernel/setup.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/clk.h> -#include <linux/init.h> -#include <linux/initrd.h> -#include <linux/sched.h> -#include <linux/console.h> -#include <linux/ioport.h> -#include <linux/bootmem.h> -#include <linux/fs.h> -#include <linux/module.h> -#include <linux/pfn.h> -#include <linux/root_dev.h> -#include <linux/cpu.h> -#include <linux/kernel.h> - -#include <asm/sections.h> -#include <asm/processor.h> -#include <asm/pgtable.h> -#include <asm/setup.h> -#include <asm/sysreg.h> - -#include <mach/board.h> -#include <mach/init.h> - -extern int root_mountflags; - -/* - * Initialize loops_per_jiffy as 5000000 (500MIPS). - * Better make it too large than too small... - */ -struct avr32_cpuinfo boot_cpu_data = { - .loops_per_jiffy = 5000000 -}; -EXPORT_SYMBOL(boot_cpu_data); - -static char __initdata command_line[COMMAND_LINE_SIZE]; - -/* - * Standard memory resources - */ -static struct resource __initdata kernel_data = { - .name = "Kernel data", - .start = 0, - .end = 0, - .flags = IORESOURCE_SYSTEM_RAM, -}; -static struct resource __initdata kernel_code = { - .name = "Kernel code", - .start = 0, - .end = 0, - .flags = IORESOURCE_SYSTEM_RAM, - .sibling = &kernel_data, -}; - -/* - * Available system RAM and reserved regions as singly linked - * lists. These lists are traversed using the sibling pointer in - * struct resource and are kept sorted at all times. - */ -static struct resource *__initdata system_ram; -static struct resource *__initdata reserved = &kernel_code; - -/* - * We need to allocate these before the bootmem allocator is up and - * running, so we need this "cache". 32 entries are probably enough - * for all but the most insanely complex systems. - */ -static struct resource __initdata res_cache[32]; -static unsigned int __initdata res_cache_next_free; - -static void __init resource_init(void) -{ - struct resource *mem, *res; - struct resource *new; - - kernel_code.start = __pa(init_mm.start_code); - - for (mem = system_ram; mem; mem = mem->sibling) { - new = alloc_bootmem_low(sizeof(struct resource)); - memcpy(new, mem, sizeof(struct resource)); - - new->sibling = NULL; - if (request_resource(&iomem_resource, new)) - printk(KERN_WARNING "Bad RAM resource %08x-%08x\n", - mem->start, mem->end); - } - - for (res = reserved; res; res = res->sibling) { - new = alloc_bootmem_low(sizeof(struct resource)); - memcpy(new, res, sizeof(struct resource)); - - new->sibling = NULL; - if (insert_resource(&iomem_resource, new)) - printk(KERN_WARNING - "Bad reserved resource %s (%08x-%08x)\n", - res->name, res->start, res->end); - } -} - -static void __init -add_physical_memory(resource_size_t start, resource_size_t end) -{ - struct resource *new, *next, **pprev; - - for (pprev = &system_ram, next = system_ram; next; - pprev = &next->sibling, next = next->sibling) { - if (end < next->start) - break; - if (start <= next->end) { - printk(KERN_WARNING - "Warning: Physical memory map is broken\n"); - printk(KERN_WARNING - "Warning: %08x-%08x overlaps %08x-%08x\n", - start, end, next->start, next->end); - return; - } - } - - if (res_cache_next_free >= ARRAY_SIZE(res_cache)) { - printk(KERN_WARNING - "Warning: Failed to add physical memory %08x-%08x\n", - start, end); - return; - } - - new = &res_cache[res_cache_next_free++]; - new->start = start; - new->end = end; - new->name = "System RAM"; - new->flags = IORESOURCE_SYSTEM_RAM; - - *pprev = new; -} - -static int __init -add_reserved_region(resource_size_t start, resource_size_t end, - const char *name) -{ - struct resource *new, *next, **pprev; - - if (end < start) - return -EINVAL; - - if (res_cache_next_free >= ARRAY_SIZE(res_cache)) - return -ENOMEM; - - for (pprev = &reserved, next = reserved; next; - pprev = &next->sibling, next = next->sibling) { - if (end < next->start) - break; - if (start <= next->end) - return -EBUSY; - } - - new = &res_cache[res_cache_next_free++]; - new->start = start; - new->end = end; - new->name = name; - new->sibling = next; - new->flags = IORESOURCE_MEM; - - *pprev = new; - - return 0; -} - -static unsigned long __init -find_free_region(const struct resource *mem, resource_size_t size, - resource_size_t align) -{ - struct resource *res; - unsigned long target; - - target = ALIGN(mem->start, align); - for (res = reserved; res; res = res->sibling) { - if ((target + size) <= res->start) - break; - if (target <= res->end) - target = ALIGN(res->end + 1, align); - } - - if ((target + size) > (mem->end + 1)) - return mem->end + 1; - - return target; -} - -static int __init -alloc_reserved_region(resource_size_t *start, resource_size_t size, - resource_size_t align, const char *name) -{ - struct resource *mem; - resource_size_t target; - int ret; - - for (mem = system_ram; mem; mem = mem->sibling) { - target = find_free_region(mem, size, align); - if (target <= mem->end) { - ret = add_reserved_region(target, target + size - 1, - name); - if (!ret) - *start = target; - return ret; - } - } - - return -ENOMEM; -} - -/* - * Early framebuffer allocation. Works as follows: - * - If fbmem_size is zero, nothing will be allocated or reserved. - * - If fbmem_start is zero when setup_bootmem() is called, - * a block of fbmem_size bytes will be reserved before bootmem - * initialization. It will be aligned to the largest page size - * that fbmem_size is a multiple of. - * - If fbmem_start is nonzero, an area of size fbmem_size will be - * reserved at the physical address fbmem_start if possible. If - * it collides with other reserved memory, a different block of - * same size will be allocated, just as if fbmem_start was zero. - * - * Board-specific code may use these variables to set up platform data - * for the framebuffer driver if fbmem_size is nonzero. - */ -resource_size_t __initdata fbmem_start; -resource_size_t __initdata fbmem_size; - -/* - * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for - * use as framebuffer. - * - * "fbmem=xxx[kKmM]@yyy[kKmM]" defines a memory region of size xxx and - * starting at yyy to be reserved for use as framebuffer. - * - * The kernel won't verify that the memory region starting at yyy - * actually contains usable RAM. - */ -static int __init early_parse_fbmem(char *p) -{ - int ret; - unsigned long align; - - fbmem_size = memparse(p, &p); - if (*p == '@') { - fbmem_start = memparse(p + 1, &p); - ret = add_reserved_region(fbmem_start, - fbmem_start + fbmem_size - 1, - "Framebuffer"); - if (ret) { - printk(KERN_WARNING - "Failed to reserve framebuffer memory\n"); - fbmem_start = 0; - } - } - - if (!fbmem_start) { - if ((fbmem_size & 0x000fffffUL) == 0) - align = 0x100000; /* 1 MiB */ - else if ((fbmem_size & 0x0000ffffUL) == 0) - align = 0x10000; /* 64 KiB */ - else - align = 0x1000; /* 4 KiB */ - - ret = alloc_reserved_region(&fbmem_start, fbmem_size, - align, "Framebuffer"); - if (ret) { - printk(KERN_WARNING - "Failed to allocate framebuffer memory\n"); - fbmem_size = 0; - } else { - memset(__va(fbmem_start), 0, fbmem_size); - } - } - - return 0; -} -early_param("fbmem", early_parse_fbmem); - -/* - * Pick out the memory size. We look for mem=size@start, - * where start and size are "size[KkMmGg]" - */ -static int __init early_mem(char *p) -{ - resource_size_t size, start; - - start = system_ram->start; - size = memparse(p, &p); - if (*p == '@') - start = memparse(p + 1, &p); - - system_ram->start = start; - system_ram->end = system_ram->start + size - 1; - return 0; -} -early_param("mem", early_mem); - -static int __init parse_tag_core(struct tag *tag) -{ - if (tag->hdr.size > 2) { - if ((tag->u.core.flags & 1) == 0) - root_mountflags &= ~MS_RDONLY; - ROOT_DEV = new_decode_dev(tag->u.core.rootdev); - } - return 0; -} -__tagtable(ATAG_CORE, parse_tag_core); - -static int __init parse_tag_mem(struct tag *tag) -{ - unsigned long start, end; - - /* - * Ignore zero-sized entries. If we're running standalone, the - * SDRAM code may emit such entries if something goes - * wrong... - */ - if (tag->u.mem_range.size == 0) - return 0; - - start = tag->u.mem_range.addr; - end = tag->u.mem_range.addr + tag->u.mem_range.size - 1; - - add_physical_memory(start, end); - return 0; -} -__tagtable(ATAG_MEM, parse_tag_mem); - -static int __init parse_tag_rdimg(struct tag *tag) -{ -#ifdef CONFIG_BLK_DEV_INITRD - struct tag_mem_range *mem = &tag->u.mem_range; - int ret; - - if (initrd_start) { - printk(KERN_WARNING - "Warning: Only the first initrd image will be used\n"); - return 0; - } - - ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1, - "initrd"); - if (ret) { - printk(KERN_WARNING - "Warning: Failed to reserve initrd memory\n"); - return ret; - } - - initrd_start = (unsigned long)__va(mem->addr); - initrd_end = initrd_start + mem->size; -#else - printk(KERN_WARNING "RAM disk image present, but " - "no initrd support in kernel, ignoring\n"); -#endif - - return 0; -} -__tagtable(ATAG_RDIMG, parse_tag_rdimg); - -static int __init parse_tag_rsvd_mem(struct tag *tag) -{ - struct tag_mem_range *mem = &tag->u.mem_range; - - return add_reserved_region(mem->addr, mem->addr + mem->size - 1, - "Reserved"); -} -__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem); - -static int __init parse_tag_cmdline(struct tag *tag) -{ - strlcpy(boot_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE); - return 0; -} -__tagtable(ATAG_CMDLINE, parse_tag_cmdline); - -static int __init parse_tag_clock(struct tag *tag) -{ - /* - * We'll figure out the clocks by peeking at the system - * manager regs directly. - */ - return 0; -} -__tagtable(ATAG_CLOCK, parse_tag_clock); - -/* - * The board_number correspond to the bd->bi_board_number in U-Boot. This - * parameter is only available during initialisation and can be used in some - * kind of board identification. - */ -u32 __initdata board_number; - -static int __init parse_tag_boardinfo(struct tag *tag) -{ - board_number = tag->u.boardinfo.board_number; - - return 0; -} -__tagtable(ATAG_BOARDINFO, parse_tag_boardinfo); - -/* - * Scan the tag table for this tag, and call its parse function. The - * tag table is built by the linker from all the __tagtable - * declarations. - */ -static int __init parse_tag(struct tag *tag) -{ - extern struct tagtable __tagtable_begin, __tagtable_end; - struct tagtable *t; - - for (t = &__tagtable_begin; t < &__tagtable_end; t++) - if (tag->hdr.tag == t->tag) { - t->parse(tag); - break; - } - - return t < &__tagtable_end; -} - -/* - * Parse all tags in the list we got from the boot loader - */ -static void __init parse_tags(struct tag *t) -{ - for (; t->hdr.tag != ATAG_NONE; t = tag_next(t)) - if (!parse_tag(t)) - printk(KERN_WARNING - "Ignoring unrecognised tag 0x%08x\n", - t->hdr.tag); -} - -/* - * Find a free memory region large enough for storing the - * bootmem bitmap. - */ -static unsigned long __init -find_bootmap_pfn(const struct resource *mem) -{ - unsigned long bootmap_pages, bootmap_len; - unsigned long node_pages = PFN_UP(resource_size(mem)); - unsigned long bootmap_start; - - bootmap_pages = bootmem_bootmap_pages(node_pages); - bootmap_len = bootmap_pages << PAGE_SHIFT; - - /* - * Find a large enough region without reserved pages for - * storing the bootmem bitmap. We can take advantage of the - * fact that all lists have been sorted. - * - * We have to check that we don't collide with any reserved - * regions, which includes the kernel image and any RAMDISK - * images. - */ - bootmap_start = find_free_region(mem, bootmap_len, PAGE_SIZE); - - return bootmap_start >> PAGE_SHIFT; -} - -#define MAX_LOWMEM HIGHMEM_START -#define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM) - -static void __init setup_bootmem(void) -{ - unsigned bootmap_size; - unsigned long first_pfn, bootmap_pfn, pages; - unsigned long max_pfn, max_low_pfn; - unsigned node = 0; - struct resource *res; - - printk(KERN_INFO "Physical memory:\n"); - for (res = system_ram; res; res = res->sibling) - printk(" %08x-%08x\n", res->start, res->end); - printk(KERN_INFO "Reserved memory:\n"); - for (res = reserved; res; res = res->sibling) - printk(" %08x-%08x: %s\n", - res->start, res->end, res->name); - - nodes_clear(node_online_map); - - if (system_ram->sibling) - printk(KERN_WARNING "Only using first memory bank\n"); - - for (res = system_ram; res; res = NULL) { - first_pfn = PFN_UP(res->start); - max_low_pfn = max_pfn = PFN_DOWN(res->end + 1); - bootmap_pfn = find_bootmap_pfn(res); - if (bootmap_pfn > max_pfn) - panic("No space for bootmem bitmap!\n"); - - if (max_low_pfn > MAX_LOWMEM_PFN) { - max_low_pfn = MAX_LOWMEM_PFN; -#ifndef CONFIG_HIGHMEM - /* - * Lowmem is memory that can be addressed - * directly through P1/P2 - */ - printk(KERN_WARNING - "Node %u: Only %ld MiB of memory will be used.\n", - node, MAX_LOWMEM >> 20); - printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); -#else -#error HIGHMEM is not supported by AVR32 yet -#endif - } - - /* Initialize the boot-time allocator with low memory only. */ - bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn, - first_pfn, max_low_pfn); - - /* - * Register fully available RAM pages with the bootmem - * allocator. - */ - pages = max_low_pfn - first_pfn; - free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn), - PFN_PHYS(pages)); - - /* Reserve space for the bootmem bitmap... */ - reserve_bootmem_node(NODE_DATA(node), - PFN_PHYS(bootmap_pfn), - bootmap_size, - BOOTMEM_DEFAULT); - - /* ...and any other reserved regions. */ - for (res = reserved; res; res = res->sibling) { - if (res->start > PFN_PHYS(max_pfn)) - break; - - /* - * resource_init will complain about partial - * overlaps, so we'll just ignore such - * resources for now. - */ - if (res->start >= PFN_PHYS(first_pfn) - && res->end < PFN_PHYS(max_pfn)) - reserve_bootmem_node(NODE_DATA(node), - res->start, - resource_size(res), - BOOTMEM_DEFAULT); - } - - node_set_online(node); - } -} - -void __init setup_arch (char **cmdline_p) -{ - struct clk *cpu_clk; - - init_mm.start_code = (unsigned long)_stext; - init_mm.end_code = (unsigned long)_etext; - init_mm.end_data = (unsigned long)_edata; - init_mm.brk = (unsigned long)_end; - - /* - * Include .init section to make allocations easier. It will - * be removed before the resource is actually requested. - */ - kernel_code.start = __pa(__init_begin); - kernel_code.end = __pa(init_mm.end_code - 1); - kernel_data.start = __pa(init_mm.end_code); - kernel_data.end = __pa(init_mm.brk - 1); - - parse_tags(bootloader_tags); - - setup_processor(); - setup_platform(); - setup_board(); - - cpu_clk = clk_get(NULL, "cpu"); - if (IS_ERR(cpu_clk)) { - printk(KERN_WARNING "Warning: Unable to get CPU clock\n"); - } else { - unsigned long cpu_hz = clk_get_rate(cpu_clk); - - /* - * Well, duh, but it's probably a good idea to - * increment the use count. - */ - clk_enable(cpu_clk); - - boot_cpu_data.clk = cpu_clk; - boot_cpu_data.loops_per_jiffy = cpu_hz * 4; - printk("CPU: Running at %lu.%03lu MHz\n", - ((cpu_hz + 500) / 1000) / 1000, - ((cpu_hz + 500) / 1000) % 1000); - } - - strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); - *cmdline_p = command_line; - parse_early_param(); - - setup_bootmem(); - -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - - paging_init(); - resource_init(); -} diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c deleted file mode 100644 index b5fcc4914fe4..000000000000 --- a/arch/avr32/kernel/signal.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * Based on linux/arch/sh/kernel/signal.c - * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima - * Copyright (C) 1991, 1992 Linus Torvalds - * - * 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/sched.h> -#include <linux/mm.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/tracehook.h> - -#include <linux/uaccess.h> -#include <asm/ucontext.h> -#include <asm/syscalls.h> - -struct rt_sigframe -{ - struct siginfo info; - struct ucontext uc; - unsigned long retcode; -}; - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - -#define COPY(x) err |= __get_user(regs->x, &sc->x) - COPY(sr); - COPY(pc); - COPY(lr); - COPY(sp); - COPY(r12); - COPY(r11); - COPY(r10); - COPY(r9); - COPY(r8); - COPY(r7); - COPY(r6); - COPY(r5); - COPY(r4); - COPY(r3); - COPY(r2); - COPY(r1); - COPY(r0); -#undef COPY - - /* - * Don't allow anyone to pretend they're running in supervisor - * mode or something... - */ - err |= !valid_user_regs(regs); - - return err; -} - - -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - sigset_t set; - - /* Always make any pending restarted system calls return -EINTR */ - current->restart_block.fn = do_no_restart_syscall; - - frame = (struct rt_sigframe __user *)regs->sp; - pr_debug("SIG return: frame = %p\n", frame); - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) - goto badframe; - - if (restore_altstack(&frame->uc.uc_stack)) - goto badframe; - - pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n", - regs->pc, regs->lr, regs->sp); - - return regs->r12; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -static int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) -{ - int err = 0; - -#define COPY(x) err |= __put_user(regs->x, &sc->x) - COPY(sr); - COPY(pc); - COPY(lr); - COPY(sp); - COPY(r12); - COPY(r11); - COPY(r10); - COPY(r9); - COPY(r8); - COPY(r7); - COPY(r6); - COPY(r5); - COPY(r4); - COPY(r3); - COPY(r2); - COPY(r1); - COPY(r0); -#undef COPY - - return err; -} - -static inline void __user * -get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize) -{ - unsigned long sp = sigsp(regs->sp, ksig); - - return (void __user *)((sp - framesize) & ~3); -} - -static int -setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - int err = 0; - - frame = get_sigframe(ksig, regs, sizeof(*frame)); - err = -EFAULT; - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) - goto out; - - /* - * Set up the return code: - * - * mov r8, __NR_rt_sigreturn - * scall - * - * Note: This will blow up since we're using a non-executable - * stack. Better use SA_RESTORER. - */ -#if __NR_rt_sigreturn > 127 -# error __NR_rt_sigreturn must be < 127 to fit in a short mov -#endif - err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20), - &frame->retcode); - - err |= copy_siginfo_to_user(&frame->info, &ksig->info); - - /* Set up the ucontext */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(NULL, &frame->uc.uc_link); - err |= __save_altstack(&frame->uc.uc_stack, regs->sp); - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - if (err) - goto out; - - regs->r12 = ksig->sig; - regs->r11 = (unsigned long) &frame->info; - regs->r10 = (unsigned long) &frame->uc; - regs->sp = (unsigned long) frame; - if (ksig->ka.sa.sa_flags & SA_RESTORER) - regs->lr = (unsigned long)ksig->ka.sa.sa_restorer; - else { - printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n", - current->comm, current->pid); - regs->lr = (unsigned long) &frame->retcode; - } - - pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n", - current->comm, current->pid, ksig->sig, regs->sp, - regs->pc, ksig->ka.sa.sa_handler, regs->lr); - - regs->pc = (unsigned long)ksig->ka.sa.sa_handler; - -out: - return err; -} - -static inline void setup_syscall_restart(struct pt_regs *regs) -{ - if (regs->r12 == -ERESTART_RESTARTBLOCK) - regs->r8 = __NR_restart_syscall; - else - regs->r12 = regs->r12_orig; - regs->pc -= 2; -} - -static inline void -handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall) -{ - int ret; - - /* - * Set up the stack frame - */ - ret = setup_rt_frame(ksig, sigmask_to_save(), regs); - - /* - * Check that the resulting registers are sane - */ - ret |= !valid_user_regs(regs); - - /* - * Block the signal if we were successful. - */ - signal_setup_done(ret, ksig, 0); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it - * doesn't want to handle. Thus you cannot kill init even with a - * SIGKILL even by mistake. - */ -static void do_signal(struct pt_regs *regs, int syscall) -{ - struct ksignal ksig; - - /* - * We want the common case to go fast, which is why we may in - * certain cases get here from kernel mode. Just return - * without doing anything if so. - */ - if (!user_mode(regs)) - return; - - get_signal(&ksig); - if (syscall) { - switch (regs->r12) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - if (ksig.sig > 0) { - regs->r12 = -EINTR; - break; - } - /* fall through */ - case -ERESTARTSYS: - if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) { - regs->r12 = -EINTR; - break; - } - /* fall through */ - case -ERESTARTNOINTR: - setup_syscall_restart(regs); - } - } - - if (!ksig.sig) { - /* No signal to deliver -- put the saved sigmask back */ - restore_saved_sigmask(); - return; - } - - handle_signal(&ksig, regs, syscall); -} - -asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) -{ - int syscall = 0; - - if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) - syscall = 1; - - if (ti->flags & _TIF_SIGPENDING) - do_signal(regs, syscall); - - if (ti->flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - } -} diff --git a/arch/avr32/kernel/stacktrace.c b/arch/avr32/kernel/stacktrace.c deleted file mode 100644 index f8cc995cf0e0..000000000000 --- a/arch/avr32/kernel/stacktrace.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Stack trace management functions - * - * Copyright (C) 2007 Atmel Corporation - * - * 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/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/stacktrace.h> -#include <linux/thread_info.h> -#include <linux/module.h> - -register unsigned long current_frame_pointer asm("r7"); - -struct stackframe { - unsigned long lr; - unsigned long fp; -}; - -/* - * Save stack-backtrace addresses into a stack_trace buffer. - */ -void save_stack_trace(struct stack_trace *trace) -{ - unsigned long low, high; - unsigned long fp; - struct stackframe *frame; - int skip = trace->skip; - - low = (unsigned long)task_stack_page(current); - high = low + THREAD_SIZE; - fp = current_frame_pointer; - - while (fp >= low && fp <= (high - 8)) { - frame = (struct stackframe *)fp; - - if (skip) { - skip--; - } else { - trace->entries[trace->nr_entries++] = frame->lr; - if (trace->nr_entries >= trace->max_entries) - break; - } - - /* - * The next frame must be at a higher address than the - * current frame. - */ - low = fp + 8; - fp = frame->fp; - } -} -EXPORT_SYMBOL_GPL(save_stack_trace); diff --git a/arch/avr32/kernel/switch_to.S b/arch/avr32/kernel/switch_to.S deleted file mode 100644 index a48d046723c5..000000000000 --- a/arch/avr32/kernel/switch_to.S +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 <asm/sysreg.h> - - .text - .global __switch_to - .type __switch_to, @function - - /* Switch thread context from "prev" to "next", returning "last" - * r12 : prev - * r11 : &prev->thread + 1 - * r10 : &next->thread - */ -__switch_to: - stm --r11, r0,r1,r2,r3,r4,r5,r6,r7,sp,lr - mfsr r9, SYSREG_SR - st.w --r11, r9 - ld.w r8, r10++ - /* - * schedule() may have been called from a mode with a different - * set of registers. Make sure we don't lose anything here. - */ - pushm r10,r12 - mtsr SYSREG_SR, r8 - frs /* flush the return stack */ - sub pc, -2 /* flush the pipeline */ - popm r10,r12 - ldm r10++, r0,r1,r2,r3,r4,r5,r6,r7,sp,pc - .size __switch_to, . - __switch_to diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S deleted file mode 100644 index cb256534ed92..000000000000 --- a/arch/avr32/kernel/syscall-stubs.S +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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. - */ - -/* - * Stubs for syscalls that require access to pt_regs or that take more - * than five parameters. - */ - -#define ARG6 r3 - - .text - .global __sys_rt_sigsuspend - .type __sys_rt_sigsuspend,@function -__sys_rt_sigsuspend: - mov r10, sp - rjmp sys_rt_sigsuspend - - .global __sys_rt_sigreturn - .type __sys_rt_sigreturn,@function -__sys_rt_sigreturn: - mov r12, sp - rjmp sys_rt_sigreturn - - .global __sys_mmap2 - .type __sys_mmap2,@function -__sys_mmap2: - pushm lr - st.w --sp, ARG6 - call sys_mmap_pgoff - sub sp, -4 - popm pc - - .global __sys_sendto - .type __sys_sendto,@function -__sys_sendto: - pushm lr - st.w --sp, ARG6 - call sys_sendto - sub sp, -4 - popm pc - - .global __sys_recvfrom - .type __sys_recvfrom,@function -__sys_recvfrom: - pushm lr - st.w --sp, ARG6 - call sys_recvfrom - sub sp, -4 - popm pc - - .global __sys_pselect6 - .type __sys_pselect6,@function -__sys_pselect6: - pushm lr - st.w --sp, ARG6 - call sys_pselect6 - sub sp, -4 - popm pc - - .global __sys_splice - .type __sys_splice,@function -__sys_splice: - pushm lr - st.w --sp, ARG6 - call sys_splice - sub sp, -4 - popm pc - - .global __sys_epoll_pwait - .type __sys_epoll_pwait,@function -__sys_epoll_pwait: - pushm lr - st.w --sp, ARG6 - call sys_epoll_pwait - sub sp, -4 - popm pc - - .global __sys_sync_file_range - .type __sys_sync_file_range,@function -__sys_sync_file_range: - pushm lr - st.w --sp, ARG6 - call sys_sync_file_range - sub sp, -4 - popm pc - - .global __sys_fallocate - .type __sys_fallocate,@function -__sys_fallocate: - pushm lr - st.w --sp, ARG6 - call sys_fallocate - sub sp, -4 - popm pc - - .global __sys_fanotify_mark - .type __sys_fanotify_mark,@function -__sys_fanotify_mark: - pushm lr - st.w --sp, ARG6 - call sys_fanotify_mark - sub sp, -4 - popm pc - - .global __sys_process_vm_readv - .type __sys_process_vm_readv,@function -__sys_process_vm_readv: - pushm lr - st.w --sp, ARG6 - call sys_process_vm_readv - sub sp, -4 - popm pc - - .global __sys_process_vm_writev - .type __sys_process_vm_writev,@function -__sys_process_vm_writev: - pushm lr - st.w --sp, ARG6 - call sys_process_vm_writev - sub sp, -4 - popm pc - - .global __sys_copy_file_range - .type __sys_copy_file_range,@function -__sys_copy_file_range: - pushm lr - st.w --sp, ARG6 - call sys_copy_file_range - sub sp, -4 - popm pc - - .global __sys_preadv2 - .type __sys_preadv2,@function -__sys_preadv2: - pushm lr - st.w --sp, ARG6 - call sys_preadv2 - sub sp, -4 - popm pc - - .global __sys_pwritev2 - .type __sys_pwritev2,@function -__sys_pwritev2: - pushm lr - st.w --sp, ARG6 - call sys_pwritev2 - sub sp, -4 - popm pc diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S deleted file mode 100644 index 774ce57f4948..000000000000 --- a/arch/avr32/kernel/syscall_table.S +++ /dev/null @@ -1,347 +0,0 @@ -/* - * AVR32 system call table - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - .section .rodata,"a",@progbits - .type sys_call_table,@object - .global sys_call_table - .align 2 -sys_call_table: - .long sys_restart_syscall - .long sys_exit - .long sys_fork - .long sys_read - .long sys_write - .long sys_open - .long sys_close - .long sys_umask - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod - .long sys_chown - .long sys_lchown - .long sys_lseek - .long sys_llseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_umount - .long sys_setuid - .long sys_getuid - .long sys_stime - .long sys_ptrace - .long sys_alarm - .long sys_pause - .long sys_utime - .long sys_newstat /* 30 */ - .long sys_newfstat - .long sys_newlstat - .long sys_access - .long sys_chroot - .long sys_sync - .long sys_fsync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_clone - .long sys_brk - .long sys_setgid - .long sys_getgid - .long sys_getcwd - .long sys_geteuid - .long sys_getegid /* 50 */ - .long sys_acct - .long sys_setfsuid - .long sys_setfsgid - .long sys_ioctl - .long sys_fcntl - .long sys_setpgid - .long sys_mremap - .long sys_setresuid - .long sys_getresuid - .long sys_setreuid /* 60 */ - .long sys_setregid - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp - .long sys_setsid - .long sys_rt_sigaction - .long __sys_rt_sigreturn - .long sys_rt_sigprocmask - .long sys_rt_sigpending /* 70 */ - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long __sys_rt_sigsuspend - .long sys_sethostname - .long sys_setrlimit - .long sys_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups /* 80 */ - .long sys_setgroups - .long sys_select - .long sys_symlink - .long sys_fchdir - .long sys_readlink - .long sys_pread64 - .long sys_pwrite64 - .long sys_swapon - .long sys_reboot - .long __sys_mmap2 /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown - .long sys_getpriority - .long sys_setpriority - .long sys_wait4 - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_vhangup - .long sys_sigaltstack - .long sys_syslog - .long sys_setitimer - .long sys_getitimer - .long sys_swapoff - .long sys_sysinfo - .long sys_ni_syscall /* was sys_ipc briefly */ - .long sys_sendfile - .long sys_setdomainname /* 110 */ - .long sys_newuname - .long sys_adjtimex - .long sys_mprotect - .long sys_vfork - .long sys_init_module - .long sys_delete_module - .long sys_quotactl - .long sys_getpgid - .long sys_bdflush - .long sys_sysfs /* 120 */ - .long sys_personality - .long sys_ni_syscall /* reserved for afs_syscall */ - .long sys_getdents - .long sys_flock - .long sys_msync - .long sys_readv - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl /* 130 */ - .long sys_mlock - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam - .long sys_sched_getparam - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max /* 140 */ - .long sys_sched_get_priority_min - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_poll - .long sys_ni_syscall /* 145 was nfsservctl */ - .long sys_setresgid - .long sys_getresgid - .long sys_prctl - .long sys_socket - .long sys_bind /* 150 */ - .long sys_connect - .long sys_listen - .long sys_accept - .long sys_getsockname - .long sys_getpeername - .long sys_socketpair - .long sys_send - .long sys_recv - .long __sys_sendto - .long __sys_recvfrom /* 160 */ - .long sys_shutdown - .long sys_setsockopt - .long sys_getsockopt - .long sys_sendmsg - .long sys_recvmsg - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 - .long sys_lstat64 - .long sys_fstat64 /* 170 */ - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - .long sys_getdents64 - .long sys_fcntl64 - .long sys_gettid - .long sys_readahead - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr /* 180 */ - .long sys_getxattr - .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill /* 190 */ - .long sys_sendfile64 - .long sys_futex - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_capget - .long sys_capset - .long sys_io_setup - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit /* 200 */ - .long sys_io_cancel - .long sys_fadvise64 - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create /* 210 */ - .long sys_timer_settime - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 /* 220 */ - .long sys_tgkill - .long sys_ni_syscall /* reserved for TUX */ - .long sys_utimes - .long sys_fadvise64_64 - .long sys_cacheflush - .long sys_ni_syscall /* sys_vserver */ - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 230 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_kexec_load - .long sys_waitid - .long sys_add_key - .long sys_request_key - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get - .long sys_inotify_init /* 240 */ - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_openat - .long sys_mkdirat - .long sys_mknodat - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 - .long sys_unlinkat - .long sys_renameat /* 250 */ - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat - .long sys_fchmodat - .long sys_faccessat - .long __sys_pselect6 - .long sys_ppoll - .long sys_unshare - .long sys_set_robust_list - .long sys_get_robust_list /* 260 */ - .long __sys_splice - .long __sys_sync_file_range - .long sys_tee - .long sys_vmsplice - .long __sys_epoll_pwait - .long sys_msgget - .long sys_msgsnd - .long sys_msgrcv - .long sys_msgctl - .long sys_semget /* 270 */ - .long sys_semop - .long sys_semctl - .long sys_semtimedop - .long sys_shmat - .long sys_shmget - .long sys_shmdt - .long sys_shmctl - .long sys_utimensat - .long sys_signalfd - .long sys_ni_syscall /* 280, was sys_timerfd */ - .long sys_eventfd - .long sys_ni_syscall /* 282, was half-implemented recvmmsg */ - .long sys_setns - .long sys_pread64 - .long sys_pwrite64 - .long sys_timerfd_create - .long __sys_fallocate - .long sys_timerfd_settime - .long sys_timerfd_gettime - .long sys_signalfd4 /* 290 */ - .long sys_eventfd2 - .long sys_epoll_create1 - .long sys_dup3 - .long sys_pipe2 - .long sys_inotify_init1 - .long sys_preadv - .long sys_pwritev - .long sys_rt_tgsigqueueinfo - .long sys_perf_event_open - .long sys_recvmmsg /* 300 */ - .long sys_fanotify_init - .long __sys_fanotify_mark - .long sys_prlimit64 - .long sys_name_to_handle_at - .long sys_open_by_handle_at - .long sys_clock_adjtime - .long sys_syncfs - .long sys_sendmmsg - .long __sys_process_vm_readv - .long __sys_process_vm_writev /* 310 */ - .long sys_kcmp - .long sys_finit_module - .long sys_sched_setattr - .long sys_sched_getattr - .long sys_renameat2 - .long sys_seccomp - .long sys_getrandom - .long sys_memfd_create - .long sys_bpf - .long sys_execveat /* 320 */ - .long sys_accept4 - .long sys_userfaultfd - .long sys_membarrier - .long sys_mlock2 - .long __sys_copy_file_range - .long __sys_preadv2 - .long __sys_pwritev2 - .long sys_pkey_mprotect - .long sys_pkey_alloc - .long sys_pkey_free /* 330 */ - .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c deleted file mode 100644 index 4d9b69615979..000000000000 --- a/arch/avr32/kernel/time.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2004-2007 Atmel Corporation - * - * 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/clk.h> -#include <linux/clockchips.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/time.h> -#include <linux/cpu.h> - -#include <asm/sysreg.h> - -#include <mach/pm.h> - -static bool disable_cpu_idle_poll; - -static u64 read_cycle_count(struct clocksource *cs) -{ - return (u64)sysreg_read(COUNT); -} - -/* - * The architectural cycle count registers are a fine clocksource unless - * the system idle loop use sleep states like "idle": the CPU cycles - * measured by COUNT (and COMPARE) don't happen during sleep states. - * Their duration also changes if cpufreq changes the CPU clock rate. - * So we rate the clocksource using COUNT as very low quality. - */ -static struct clocksource counter = { - .name = "avr32_counter", - .rating = 50, - .read = read_cycle_count, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evdev = dev_id; - - if (unlikely(!(intc_get_pending(0) & 1))) - return IRQ_NONE; - - /* - * Disable the interrupt until the clockevent subsystem - * reprograms it. - */ - sysreg_write(COMPARE, 0); - - evdev->event_handler(evdev); - return IRQ_HANDLED; -} - -static struct irqaction timer_irqaction = { - .handler = timer_interrupt, - /* Oprofile uses the same irq as the timer, so allow it to be shared */ - .flags = IRQF_TIMER | IRQF_SHARED, - .name = "avr32_comparator", -}; - -static int comparator_next_event(unsigned long delta, - struct clock_event_device *evdev) -{ - unsigned long flags; - - raw_local_irq_save(flags); - - /* The time to read COUNT then update COMPARE must be less - * than the min_delta_ns value for this clockevent source. - */ - sysreg_write(COMPARE, (sysreg_read(COUNT) + delta) ? : 1); - - raw_local_irq_restore(flags); - - return 0; -} - -static int comparator_shutdown(struct clock_event_device *evdev) -{ - pr_debug("%s: %s\n", __func__, evdev->name); - sysreg_write(COMPARE, 0); - - if (disable_cpu_idle_poll) { - disable_cpu_idle_poll = false; - /* - * Only disable idle poll if we have forced that - * in a previous call. - */ - cpu_idle_poll_ctrl(false); - } - return 0; -} - -static int comparator_set_oneshot(struct clock_event_device *evdev) -{ - pr_debug("%s: %s\n", __func__, evdev->name); - - disable_cpu_idle_poll = true; - /* - * If we're using the COUNT and COMPARE registers we - * need to force idle poll. - */ - cpu_idle_poll_ctrl(true); - - return 0; -} - -static struct clock_event_device comparator = { - .name = "avr32_comparator", - .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 16, - .rating = 50, - .set_next_event = comparator_next_event, - .set_state_shutdown = comparator_shutdown, - .set_state_oneshot = comparator_set_oneshot, - .tick_resume = comparator_set_oneshot, -}; - -void read_persistent_clock(struct timespec *ts) -{ - ts->tv_sec = mktime(2007, 1, 1, 0, 0, 0); - ts->tv_nsec = 0; -} - -void __init time_init(void) -{ - unsigned long counter_hz; - int ret; - - /* figure rate for counter */ - counter_hz = clk_get_rate(boot_cpu_data.clk); - ret = clocksource_register_hz(&counter, counter_hz); - if (ret) - pr_debug("timer: could not register clocksource: %d\n", ret); - - /* setup COMPARE clockevent */ - comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift); - comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator); - comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1; - comparator.cpumask = cpumask_of(0); - - sysreg_write(COMPARE, 0); - timer_irqaction.dev_id = &comparator; - - ret = setup_irq(0, &timer_irqaction); - if (ret) - pr_debug("timer: could not request IRQ 0: %d\n", ret); - else { - clockevents_register_device(&comparator); - - pr_info("%s: irq 0, %lu.%03lu MHz\n", comparator.name, - ((counter_hz + 500) / 1000) / 1000, - ((counter_hz + 500) / 1000) % 1000); - } -} diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c deleted file mode 100644 index 50b541325025..000000000000 --- a/arch/avr32/kernel/traps.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/bug.h> -#include <linux/hardirq.h> -#include <linux/init.h> -#include <linux/kallsyms.h> -#include <linux/kdebug.h> -#include <linux/extable.h> -#include <linux/module.h> /* print_modules */ -#include <linux/notifier.h> -#include <linux/sched/signal.h> -#include <linux/uaccess.h> - -#include <asm/addrspace.h> -#include <asm/mmu_context.h> -#include <asm/ocd.h> -#include <asm/sysreg.h> -#include <asm/traps.h> - -static DEFINE_SPINLOCK(die_lock); - -void die(const char *str, struct pt_regs *regs, long err) -{ - static int die_counter; - - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); - - printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n", - str, err, ++die_counter); - - printk(KERN_EMERG); - -#ifdef CONFIG_PREEMPT - printk(KERN_CONT "PREEMPT "); -#endif -#ifdef CONFIG_FRAME_POINTER - printk(KERN_CONT "FRAME_POINTER "); -#endif - if (current_cpu_data.features & AVR32_FEATURE_OCD) { - unsigned long did = ocd_read(DID); - printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n", - (did >> 1) & 0x7ff, - (did >> 12) & 0x7fff, - (did >> 28) & 0xf); - } else { - printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n", - current_cpu_data.arch_type, - current_cpu_data.arch_revision, - current_cpu_data.cpu_type, - current_cpu_data.cpu_revision); - } - - print_modules(); - show_regs_log_lvl(regs, KERN_EMERG); - show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); - bust_spinlocks(0); - add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); - spin_unlock_irq(&die_lock); - - if (in_interrupt()) - panic("Fatal exception in interrupt"); - - if (panic_on_oops) - panic("Fatal exception"); - - do_exit(err); -} - -void _exception(long signr, struct pt_regs *regs, int code, - unsigned long addr) -{ - siginfo_t info; - - if (!user_mode(regs)) { - const struct exception_table_entry *fixup; - - /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - die("Unhandled exception in kernel mode", regs, signr); - } - - memset(&info, 0, sizeof(info)); - info.si_signo = signr; - info.si_code = code; - info.si_addr = (void __user *)addr; - force_sig_info(signr, &info, current); -} - -asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs) -{ - int ret; - - nmi_enter(); - - ret = notify_die(DIE_NMI, "NMI", regs, 0, ecr, SIGINT); - switch (ret) { - case NOTIFY_OK: - case NOTIFY_STOP: - break; - case NOTIFY_BAD: - die("Fatal Non-Maskable Interrupt", regs, SIGINT); - default: - printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n"); - nmi_disable(); - break; - } - nmi_exit(); -} - -asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs) -{ - die("Critical exception", regs, SIGKILL); -} - -asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs) -{ - _exception(SIGBUS, regs, BUS_ADRALN, regs->pc); -} - -/* This way of handling undefined instructions is stolen from ARM */ -static LIST_HEAD(undef_hook); -static DEFINE_SPINLOCK(undef_lock); - -void register_undef_hook(struct undef_hook *hook) -{ - spin_lock_irq(&undef_lock); - list_add(&hook->node, &undef_hook); - spin_unlock_irq(&undef_lock); -} - -void unregister_undef_hook(struct undef_hook *hook) -{ - spin_lock_irq(&undef_lock); - list_del(&hook->node); - spin_unlock_irq(&undef_lock); -} - -static int do_cop_absent(u32 insn) -{ - int cop_nr; - u32 cpucr; - - if ((insn & 0xfdf00000) == 0xf1900000) - /* LDC0 */ - cop_nr = 0; - else - cop_nr = (insn >> 13) & 0x7; - - /* Try enabling the coprocessor */ - cpucr = sysreg_read(CPUCR); - cpucr |= (1 << (24 + cop_nr)); - sysreg_write(CPUCR, cpucr); - - cpucr = sysreg_read(CPUCR); - if (!(cpucr & (1 << (24 + cop_nr)))) - return -ENODEV; - - return 0; -} - -#ifdef CONFIG_BUG -int is_valid_bugaddr(unsigned long pc) -{ - unsigned short opcode; - - if (pc < PAGE_OFFSET) - return 0; - if (probe_kernel_address((u16 *)pc, opcode)) - return 0; - - return opcode == AVR32_BUG_OPCODE; -} -#endif - -asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) -{ - u32 insn; - struct undef_hook *hook; - void __user *pc; - long code; - -#ifdef CONFIG_BUG - if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) { - enum bug_trap_type type; - - type = report_bug(regs->pc, regs); - switch (type) { - case BUG_TRAP_TYPE_NONE: - break; - case BUG_TRAP_TYPE_WARN: - regs->pc += 2; - return; - case BUG_TRAP_TYPE_BUG: - die("Kernel BUG", regs, SIGKILL); - } - } -#endif - - local_irq_enable(); - - if (user_mode(regs)) { - pc = (void __user *)instruction_pointer(regs); - if (get_user(insn, (u32 __user *)pc)) - goto invalid_area; - - if (ecr == ECR_COPROC_ABSENT && !do_cop_absent(insn)) - return; - - spin_lock_irq(&undef_lock); - list_for_each_entry(hook, &undef_hook, node) { - if ((insn & hook->insn_mask) == hook->insn_val) { - if (hook->fn(regs, insn) == 0) { - spin_unlock_irq(&undef_lock); - return; - } - } - } - spin_unlock_irq(&undef_lock); - } - - switch (ecr) { - case ECR_PRIVILEGE_VIOLATION: - code = ILL_PRVOPC; - break; - case ECR_COPROC_ABSENT: - code = ILL_COPROC; - break; - default: - code = ILL_ILLOPC; - break; - } - - _exception(SIGILL, regs, code, regs->pc); - return; - -invalid_area: - _exception(SIGSEGV, regs, SEGV_MAPERR, regs->pc); -} - -asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs) -{ - /* We have no FPU yet */ - _exception(SIGILL, regs, ILL_COPROC, regs->pc); -} - - -void __init trap_init(void) -{ - -} diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S deleted file mode 100644 index 17f2730eb497..000000000000 --- a/arch/avr32/kernel/vmlinux.lds.S +++ /dev/null @@ -1,89 +0,0 @@ -/* - * AVR32 linker script for the Linux kernel - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ -#define LOAD_OFFSET 0x00000000 -#include <asm-generic/vmlinux.lds.h> -#include <asm/cache.h> -#include <asm/thread_info.h> - -OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32") -OUTPUT_ARCH(avr32) -ENTRY(_start) - -/* Big endian */ -jiffies = jiffies_64 + 4; - -SECTIONS -{ - . = CONFIG_ENTRY_ADDRESS; - .init : AT(ADDR(.init) - LOAD_OFFSET) { - _text = .; - __init_begin = .; - _sinittext = .; - *(.text.reset) - INIT_TEXT - /* - * .exit.text is discarded at runtime, not - * link time, to deal with references from - * __bug_table - */ - EXIT_TEXT - _einittext = .; - . = ALIGN(4); - __tagtable_begin = .; - *(.taglist.init) - __tagtable_end = .; - } - INIT_DATA_SECTION(16) - . = ALIGN(PAGE_SIZE); - __init_end = .; - - .text : AT(ADDR(.text) - LOAD_OFFSET) { - _evba = .; - _stext = .; - *(.ex.text) - *(.irq.text) - KPROBES_TEXT - TEXT_TEXT - SCHED_TEXT - CPUIDLE_TEXT - LOCK_TEXT - *(.fixup) - *(.gnu.warning) - _etext = .; - } = 0xd703d703 - - EXCEPTION_TABLE(4) - RODATA - - .data : AT(ADDR(.data) - LOAD_OFFSET) { - _data = .; - _sdata = .; - - INIT_TASK_DATA(THREAD_SIZE) - PAGE_ALIGNED_DATA(PAGE_SIZE); - CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) - *(.data.rel*) - DATA_DATA - CONSTRUCTORS - - _edata = .; - } - - BSS_SECTION(0, 8, 8) - _end = .; - - DWARF_DEBUG - - /* When something in the kernel is NOT compiled as a module, the module - * cleanup code and data are put into these segments. Both can then be - * thrown away, as cleanup code is never called unless it's a module. - */ - DISCARDS -} diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile deleted file mode 100644 index 084d95bac5e7..000000000000 --- a/arch/avr32/lib/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for AVR32-specific library files -# - -lib-y := copy_user.o clear_user.o -lib-y += strncpy_from_user.o strnlen_user.o -lib-y += delay.o memset.o memcpy.o findbit.o -lib-y += csum_partial.o csum_partial_copy_generic.o -lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o -lib-y += io-readsb.o io-writesb.o -lib-y += __avr32_lsl64.o __avr32_lsr64.o __avr32_asr64.o diff --git a/arch/avr32/lib/__avr32_asr64.S b/arch/avr32/lib/__avr32_asr64.S deleted file mode 100644 index 368b6bca4c76..000000000000 --- a/arch/avr32/lib/__avr32_asr64.S +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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. - */ - - /* - * DWtype __avr32_asr64(DWtype u, word_type b) - */ - .text - .global __avr32_asr64 - .type __avr32_asr64,@function -__avr32_asr64: - cp.w r12, 0 - reteq r12 - - rsub r9, r12, 32 - brle 1f - - lsl r8, r11, r9 - lsr r10, r10, r12 - asr r11, r11, r12 - or r10, r8 - retal r12 - -1: neg r9 - asr r10, r11, r9 - asr r11, 31 - retal r12 diff --git a/arch/avr32/lib/__avr32_lsl64.S b/arch/avr32/lib/__avr32_lsl64.S deleted file mode 100644 index f1dbc2b36257..000000000000 --- a/arch/avr32/lib/__avr32_lsl64.S +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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. - */ - - /* - * DWtype __avr32_lsl64(DWtype u, word_type b) - */ - .text - .global __avr32_lsl64 - .type __avr32_lsl64,@function -__avr32_lsl64: - cp.w r12, 0 - reteq r12 - - rsub r9, r12, 32 - brle 1f - - lsr r8, r10, r9 - lsl r10, r10, r12 - lsl r11, r11, r12 - or r11, r8 - retal r12 - -1: neg r9 - lsl r11, r10, r9 - mov r10, 0 - retal r12 diff --git a/arch/avr32/lib/__avr32_lsr64.S b/arch/avr32/lib/__avr32_lsr64.S deleted file mode 100644 index e65bb7f0d24c..000000000000 --- a/arch/avr32/lib/__avr32_lsr64.S +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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. - */ - - /* - * DWtype __avr32_lsr64(DWtype u, word_type b) - */ - .text - .global __avr32_lsr64 - .type __avr32_lsr64,@function -__avr32_lsr64: - cp.w r12, 0 - reteq r12 - - rsub r9, r12, 32 - brle 1f - - lsl r8, r11, r9 - lsr r11, r11, r12 - lsr r10, r10, r12 - or r10, r8 - retal r12 - -1: neg r9 - lsr r10, r11, r9 - mov r11, 0 - retal r12 diff --git a/arch/avr32/lib/clear_user.S b/arch/avr32/lib/clear_user.S deleted file mode 100644 index d8991b6f8eb7..000000000000 --- a/arch/avr32/lib/clear_user.S +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2004-2006 Atmel Corporation - * - * 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 <asm/page.h> -#include <asm/thread_info.h> -#include <asm/asm.h> - - .text - .align 1 - .global clear_user - .type clear_user, "function" -clear_user: - branch_if_kernel r8, __clear_user - ret_if_privileged r8, r12, r11, r11 - - .global __clear_user - .type __clear_user, "function" -__clear_user: - mov r9, r12 - mov r8, 0 - andl r9, 3, COH - brne 5f - -1: sub r11, 4 - brlt 2f - -10: st.w r12++, r8 - sub r11, 4 - brge 10b - -2: sub r11, -4 - reteq 0 - - /* Unaligned count or address */ - bld r11, 1 - brcc 12f -11: st.h r12++, r8 - sub r11, 2 - reteq 0 -12: st.b r12++, r8 - retal 0 - - /* Unaligned address */ -5: cp.w r11, 4 - brlt 2b - - lsl r9, 2 - add pc, pc, r9 -13: st.b r12++, r8 - sub r11, 1 -14: st.b r12++, r8 - sub r11, 1 -15: st.b r12++, r8 - sub r11, 1 - rjmp 1b - - .size clear_user, . - clear_user - .size __clear_user, . - __clear_user - - .section .fixup, "ax" - .align 1 -18: sub r11, -4 -19: retal r11 - - .section __ex_table, "a" - .align 2 - .long 10b, 18b - .long 11b, 19b - .long 12b, 19b - .long 13b, 19b - .long 14b, 19b - .long 15b, 19b diff --git a/arch/avr32/lib/copy_user.S b/arch/avr32/lib/copy_user.S deleted file mode 100644 index 075373471da1..000000000000 --- a/arch/avr32/lib/copy_user.S +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copy to/from userspace with optional address space checking. - * - * Copyright 2004-2006 Atmel Corporation - * - * 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 <asm/page.h> -#include <asm/thread_info.h> -#include <asm/asm.h> - - /* - * __kernel_size_t - * __copy_user(void *to, const void *from, __kernel_size_t n) - * - * Returns the number of bytes not copied. Might be off by - * max 3 bytes if we get a fault in the main loop. - * - * The address-space checking functions simply fall through to - * the non-checking version. - */ - .text - .align 1 - .global ___copy_from_user - .type ___copy_from_user, @function -___copy_from_user: - branch_if_kernel r8, __copy_user - ret_if_privileged r8, r11, r10, r10 - rjmp __copy_user - .size ___copy_from_user, . - ___copy_from_user - - .global copy_to_user - .type copy_to_user, @function -copy_to_user: - branch_if_kernel r8, __copy_user - ret_if_privileged r8, r12, r10, r10 - .size copy_to_user, . - copy_to_user - - .global __copy_user - .type __copy_user, @function -__copy_user: - mov r9, r11 - andl r9, 3, COH - brne 6f - - /* At this point, from is word-aligned */ -1: sub r10, 4 - brlt 3f - -2: -10: ld.w r8, r11++ -11: st.w r12++, r8 - sub r10, 4 - brge 2b - -3: sub r10, -4 - reteq 0 - - /* - * Handle unaligned count. Need to be careful with r10 here so - * that we return the correct value even if we get a fault - */ -4: -20: ld.ub r8, r11++ -21: st.b r12++, r8 - sub r10, 1 - reteq 0 -22: ld.ub r8, r11++ -23: st.b r12++, r8 - sub r10, 1 - reteq 0 -24: ld.ub r8, r11++ -25: st.b r12++, r8 - retal 0 - - /* Handle unaligned from-pointer */ -6: cp.w r10, 4 - brlt 4b - rsub r9, r9, 4 - -30: ld.ub r8, r11++ -31: st.b r12++, r8 - sub r10, 1 - sub r9, 1 - breq 1b -32: ld.ub r8, r11++ -33: st.b r12++, r8 - sub r10, 1 - sub r9, 1 - breq 1b -34: ld.ub r8, r11++ -35: st.b r12++, r8 - sub r10, 1 - rjmp 1b - .size __copy_user, . - __copy_user - - .section .fixup,"ax" - .align 1 -19: sub r10, -4 -29: retal r10 - - .section __ex_table,"a" - .align 2 - .long 10b, 19b - .long 11b, 19b - .long 20b, 29b - .long 21b, 29b - .long 22b, 29b - .long 23b, 29b - .long 24b, 29b - .long 25b, 29b - .long 30b, 29b - .long 31b, 29b - .long 32b, 29b - .long 33b, 29b - .long 34b, 29b - .long 35b, 29b diff --git a/arch/avr32/lib/csum_partial.S b/arch/avr32/lib/csum_partial.S deleted file mode 100644 index 6a262b528eb7..000000000000 --- a/arch/avr32/lib/csum_partial.S +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - /* - * unsigned int csum_partial(const unsigned char *buff, - * int len, unsigned int sum) - */ - .text - .global csum_partial - .type csum_partial,"function" - .align 1 -csum_partial: - /* checksum complete words, aligned or not */ -3: sub r11, 4 - brlt 5f -4: ld.w r9, r12++ - add r10, r9 - acr r10 - sub r11, 4 - brge 4b - - /* return if we had a whole number of words */ -5: sub r11, -4 - reteq r10 - - /* checksum any remaining bytes at the end */ - mov r9, 0 - mov r8, 0 - cp r11, 2 - brlt 6f - ld.uh r9, r12++ - sub r11, 2 - breq 7f - lsl r9, 16 -6: ld.ub r8, r12++ - lsl r8, 8 -7: or r9, r8 - add r10, r9 - acr r10 - - retal r10 - .size csum_partial, . - csum_partial diff --git a/arch/avr32/lib/csum_partial_copy_generic.S b/arch/avr32/lib/csum_partial_copy_generic.S deleted file mode 100644 index a3a0f9b8929c..000000000000 --- a/arch/avr32/lib/csum_partial_copy_generic.S +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 <asm/errno.h> -#include <asm/asm.h> - - /* - * unsigned int csum_partial_copy_generic(const char *src, char *dst, int len - * int sum, int *src_err_ptr, - * int *dst_err_ptr) - * - * Copy src to dst while checksumming, otherwise like csum_partial. - */ - - .macro ld_src size, reg, ptr -9999: ld.\size \reg, \ptr - .section __ex_table, "a" - .long 9999b, fixup_ld_src - .previous - .endm - - .macro st_dst size, ptr, reg -9999: st.\size \ptr, \reg - .section __ex_table, "a" - .long 9999b, fixup_st_dst - .previous - .endm - - .text - .global csum_partial_copy_generic - .type csum_partial_copy_generic,"function" - .align 1 -csum_partial_copy_generic: - pushm r4-r7,lr - - /* The inner loop */ -1: sub r10, 4 - brlt 5f -2: ld_src w, r5, r12++ - st_dst w, r11++, r5 - add r9, r5 - acr r9 - sub r10, 4 - brge 2b - - /* return if we had a whole number of words */ -5: sub r10, -4 - brne 7f - -6: mov r12, r9 - popm r4-r7,pc - - /* handle additional bytes at the tail */ -7: mov r5, 0 - mov r4, 32 -8: ld_src ub, r6, r12++ - st_dst b, r11++, r6 - lsl r5, 8 - sub r4, 8 - bfins r5, r6, 0, 8 - sub r10, 1 - brne 8b - - lsl r5, r5, r4 - add r9, r5 - acr r9 - rjmp 6b - - /* Exception handler */ - .section .fixup,"ax" - .align 1 -fixup_ld_src: - mov r9, -EFAULT - cp.w r8, 0 - breq 1f - st.w r8[0], r9 - -1: /* - * TODO: zero the complete destination - computing the rest - * is too much work - */ - - mov r9, 0 - rjmp 6b - -fixup_st_dst: - mov r9, -EFAULT - lddsp r8, sp[20] - cp.w r8, 0 - breq 1f - st.w r8[0], r9 -1: mov r9, 0 - rjmp 6b - - .previous diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c deleted file mode 100644 index c2f4a07dcda1..000000000000 --- a/arch/avr32/lib/delay.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Precise Delay Loops for avr32 - * - * Copyright (C) 1993 Linus Torvalds - * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/delay.h> -#include <linux/module.h> -#include <linux/timex.h> -#include <linux/param.h> -#include <linux/types.h> -#include <linux/init.h> - -#include <asm/processor.h> -#include <asm/sysreg.h> - -int read_current_timer(unsigned long *timer_value) -{ - *timer_value = sysreg_read(COUNT); - return 0; -} - -void __delay(unsigned long loops) -{ - unsigned bclock, now; - - bclock = sysreg_read(COUNT); - do { - now = sysreg_read(COUNT); - } while ((now - bclock) < loops); -} - -inline void __const_udelay(unsigned long xloops) -{ - unsigned long long loops; - - asm("mulu.d %0, %1, %2" - : "=r"(loops) - : "r"(current_cpu_data.loops_per_jiffy * HZ), "r"(xloops)); - __delay(loops >> 32); -} - -void __udelay(unsigned long usecs) -{ - __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ -} - -void __ndelay(unsigned long nsecs) -{ - __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ -} diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S deleted file mode 100644 index b93586460be6..000000000000 --- a/arch/avr32/lib/findbit.S +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2006 Atmel Corporation - * - * 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> - - .text - /* - * unsigned long find_first_zero_bit(const unsigned long *addr, - * unsigned long size) - */ -ENTRY(find_first_zero_bit) - cp.w r11, 0 - reteq r11 - mov r9, r11 -1: ld.w r8, r12[0] - com r8 - brne .L_found - sub r12, -4 - sub r9, 32 - brgt 1b - retal r11 - - /* - * unsigned long find_next_zero_bit(const unsigned long *addr, - * unsigned long size, - * unsigned long offset) - */ -ENTRY(find_next_zero_bit) - lsr r8, r10, 5 - sub r9, r11, r10 - retle r11 - - lsl r8, 2 - add r12, r8 - andl r10, 31, COH - breq 1f - - /* offset is not word-aligned. Handle the first (32 - r10) bits */ - ld.w r8, r12[0] - com r8 - sub r12, -4 - lsr r8, r8, r10 - brne .L_found - - /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ - add r9, r10 - sub r9, 32 - retle r11 - - /* Main loop. offset must be word-aligned */ -1: ld.w r8, r12[0] - com r8 - brne .L_found - sub r12, -4 - sub r9, 32 - brgt 1b - retal r11 - - /* Common return path for when a bit is actually found. */ -.L_found: - brev r8 - clz r10, r8 - rsub r9, r11 - add r10, r9 - - /* XXX: If we don't have to return exactly "size" when the bit - is not found, we may drop this "min" thing */ - min r12, r11, r10 - retal r12 - - /* - * unsigned long find_first_bit(const unsigned long *addr, - * unsigned long size) - */ -ENTRY(find_first_bit) - cp.w r11, 0 - reteq r11 - mov r9, r11 -1: ld.w r8, r12[0] - cp.w r8, 0 - brne .L_found - sub r12, -4 - sub r9, 32 - brgt 1b - retal r11 - - /* - * unsigned long find_next_bit(const unsigned long *addr, - * unsigned long size, - * unsigned long offset) - */ -ENTRY(find_next_bit) - lsr r8, r10, 5 - sub r9, r11, r10 - retle r11 - - lsl r8, 2 - add r12, r8 - andl r10, 31, COH - breq 1f - - /* offset is not word-aligned. Handle the first (32 - r10) bits */ - ld.w r8, r12[0] - sub r12, -4 - lsr r8, r8, r10 - brne .L_found - - /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ - add r9, r10 - sub r9, 32 - retle r11 - - /* Main loop. offset must be word-aligned */ -1: ld.w r8, r12[0] - cp.w r8, 0 - brne .L_found - sub r12, -4 - sub r9, 32 - brgt 1b - retal r11 - -ENTRY(find_next_bit_le) - lsr r8, r10, 5 - sub r9, r11, r10 - retle r11 - - lsl r8, 2 - add r12, r8 - andl r10, 31, COH - breq 1f - - /* offset is not word-aligned. Handle the first (32 - r10) bits */ - ldswp.w r8, r12[0] - sub r12, -4 - lsr r8, r8, r10 - brne .L_found - - /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ - add r9, r10 - sub r9, 32 - retle r11 - - /* Main loop. offset must be word-aligned */ -1: ldswp.w r8, r12[0] - cp.w r8, 0 - brne .L_found - sub r12, -4 - sub r9, 32 - brgt 1b - retal r11 - -ENTRY(find_next_zero_bit_le) - lsr r8, r10, 5 - sub r9, r11, r10 - retle r11 - - lsl r8, 2 - add r12, r8 - andl r10, 31, COH - breq 1f - - /* offset is not word-aligned. Handle the first (32 - r10) bits */ - ldswp.w r8, r12[0] - sub r12, -4 - com r8 - lsr r8, r8, r10 - brne .L_found - - /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ - add r9, r10 - sub r9, 32 - retle r11 - - /* Main loop. offset must be word-aligned */ -1: ldswp.w r8, r12[0] - com r8 - brne .L_found - sub r12, -4 - sub r9, 32 - brgt 1b - retal r11 diff --git a/arch/avr32/lib/io-readsb.S b/arch/avr32/lib/io-readsb.S deleted file mode 100644 index cb2d86945559..000000000000 --- a/arch/avr32/lib/io-readsb.S +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - .text -.Lnot_word_aligned: -1: ld.ub r8, r12[0] - sub r10, 1 - st.b r11++, r8 - reteq r12 - tst r11, r9 - brne 1b - - /* fall through */ - - .global __raw_readsb - .type __raw_readsb,@function -__raw_readsb: - cp.w r10, 0 - mov r9, 3 - reteq r12 - - tst r11, r9 - brne .Lnot_word_aligned - - sub r10, 4 - brlt 2f - -1: ldins.b r8:t, r12[0] - ldins.b r8:u, r12[0] - ldins.b r8:l, r12[0] - ldins.b r8:b, r12[0] - st.w r11++, r8 - sub r10, 4 - brge 1b - -2: sub r10, -4 - reteq r12 - -3: ld.ub r8, r12[0] - sub r10, 1 - st.b r11++, r8 - brne 3b - - retal r12 diff --git a/arch/avr32/lib/io-readsl.S b/arch/avr32/lib/io-readsl.S deleted file mode 100644 index b103511ed6c4..000000000000 --- a/arch/avr32/lib/io-readsl.S +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - .global __raw_readsl - .type __raw_readsl,@function -__raw_readsl: - cp.w r10, 0 - reteq r12 - - /* - * If r11 isn't properly aligned, we might get an exception on - * some implementations. But there's not much we can do about it. - */ -1: ld.w r8, r12[0] - sub r10, 1 - st.w r11++, r8 - brne 1b - - retal r12 diff --git a/arch/avr32/lib/io-readsw.S b/arch/avr32/lib/io-readsw.S deleted file mode 100644 index 456be9909027..000000000000 --- a/arch/avr32/lib/io-readsw.S +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - -.Lnot_word_aligned: - /* - * Bad alignment will cause a hardware exception, which is as - * good as anything. No need for us to check for proper alignment. - */ - ld.uh r8, r12[0] - sub r10, 1 - st.h r11++, r8 - - /* fall through */ - - .global __raw_readsw - .type __raw_readsw,@function -__raw_readsw: - cp.w r10, 0 - reteq r12 - mov r9, 3 - tst r11, r9 - brne .Lnot_word_aligned - - sub r10, 2 - brlt 2f - -1: ldins.h r8:t, r12[0] - ldins.h r8:b, r12[0] - st.w r11++, r8 - sub r10, 2 - brge 1b - -2: sub r10, -2 - reteq r12 - - ld.uh r8, r12[0] - st.h r11++, r8 - retal r12 diff --git a/arch/avr32/lib/io-writesb.S b/arch/avr32/lib/io-writesb.S deleted file mode 100644 index b4ebaacccf68..000000000000 --- a/arch/avr32/lib/io-writesb.S +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - .text -.Lnot_word_aligned: -1: ld.ub r8, r11++ - sub r10, 1 - st.b r12[0], r8 - reteq r12 - tst r11, r9 - brne 1b - - /* fall through */ - - .global __raw_writesb - .type __raw_writesb,@function -__raw_writesb: - cp.w r10, 0 - mov r9, 3 - reteq r12 - - tst r11, r9 - brne .Lnot_word_aligned - - sub r10, 4 - brlt 2f - -1: ld.w r8, r11++ - bfextu r9, r8, 24, 8 - st.b r12[0], r9 - bfextu r9, r8, 16, 8 - st.b r12[0], r9 - bfextu r9, r8, 8, 8 - st.b r12[0], r9 - st.b r12[0], r8 - sub r10, 4 - brge 1b - -2: sub r10, -4 - reteq r12 - -3: ld.ub r8, r11++ - sub r10, 1 - st.b r12[0], r8 - brne 3b - - retal r12 diff --git a/arch/avr32/lib/io-writesl.S b/arch/avr32/lib/io-writesl.S deleted file mode 100644 index 22138b3a16e5..000000000000 --- a/arch/avr32/lib/io-writesl.S +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - .global __raw_writesl - .type __raw_writesl,@function -__raw_writesl: - cp.w r10, 0 - reteq r12 - -1: ld.w r8, r11++ - sub r10, 1 - st.w r12[0], r8 - brne 1b - - retal r12 diff --git a/arch/avr32/lib/io-writesw.S b/arch/avr32/lib/io-writesw.S deleted file mode 100644 index 8c4a53f1c52a..000000000000 --- a/arch/avr32/lib/io-writesw.S +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - -.Lnot_word_aligned: - ld.uh r8, r11++ - sub r10, 1 - st.h r12[0], r8 - - .global __raw_writesw - .type __raw_writesw,@function -__raw_writesw: - cp.w r10, 0 - mov r9, 3 - reteq r12 - tst r11, r9 - brne .Lnot_word_aligned - - sub r10, 2 - brlt 2f - -1: ld.w r8, r11++ - bfextu r9, r8, 16, 16 - st.h r12[0], r9 - st.h r12[0], r8 - sub r10, 2 - brge 1b - -2: sub r10, -2 - reteq r12 - - ld.uh r8, r11++ - st.h r12[0], r8 - retal r12 diff --git a/arch/avr32/lib/memcpy.S b/arch/avr32/lib/memcpy.S deleted file mode 100644 index c2ca49d705af..000000000000 --- a/arch/avr32/lib/memcpy.S +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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. - */ - - /* - * void *memcpy(void *to, const void *from, unsigned long n) - * - * This implementation does word-aligned loads in the main loop, - * possibly sacrificing alignment of stores. - * - * Hopefully, in most cases, both "to" and "from" will be - * word-aligned to begin with. - */ - .text - .global memcpy - .type memcpy, @function -memcpy: - mov r9, r11 - andl r9, 3, COH - brne 1f - - /* At this point, "from" is word-aligned */ -2: mov r9, r12 -5: sub r10, 4 - brlt 4f - -3: ld.w r8, r11++ - sub r10, 4 - st.w r12++, r8 - brge 3b - -4: neg r10 - reteq r9 - - /* Handle unaligned count */ - lsl r10, 2 - add pc, pc, r10 - ld.ub r8, r11++ - st.b r12++, r8 - ld.ub r8, r11++ - st.b r12++, r8 - ld.ub r8, r11++ - st.b r12++, r8 - retal r9 - - /* Handle unaligned "from" pointer */ -1: sub r10, 4 - movlt r9, r12 - brlt 4b - add r10, r9 - lsl r9, 2 - add pc, pc, r9 - ld.ub r8, r11++ - st.b r12++, r8 - ld.ub r8, r11++ - st.b r12++, r8 - ld.ub r8, r11++ - st.b r12++, r8 - mov r8, r12 - add pc, pc, r9 - sub r8, 1 - nop - sub r8, 1 - nop - sub r8, 1 - nop - mov r9, r8 - rjmp 5b diff --git a/arch/avr32/lib/memset.S b/arch/avr32/lib/memset.S deleted file mode 100644 index 40da32c0480c..000000000000 --- a/arch/avr32/lib/memset.S +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * Based on linux/arch/arm/lib/memset.S - * Copyright (C) 1995-2000 Russell King - * - * 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 <asm/asm.h> - - /* - * r12: void *b - * r11: int c - * r10: size_t len - * - * Returns b in r12 - */ - .text - .global memset - .type memset, @function - .align 5 -memset: - mov r9, r12 - mov r8, r12 - or r11, r11, r11 << 8 - andl r9, 3, COH - brne 1f - -2: or r11, r11, r11 << 16 - sub r10, 4 - brlt 5f - - /* Let's do some real work */ -4: st.w r8++, r11 - sub r10, 4 - brge 4b - - /* - * When we get here, we've got less than 4 bytes to set. r10 - * might be negative. - */ -5: sub r10, -4 - reteq r12 - - /* Fastpath ends here, exactly 32 bytes from memset */ - - /* Handle unaligned count or pointer */ - bld r10, 1 - brcc 6f - st.b r8++, r11 - st.b r8++, r11 - bld r10, 0 - retcc r12 -6: st.b r8++, r11 - retal r12 - - /* Handle unaligned pointer */ -1: sub r10, 4 - brlt 5b - add r10, r9 - lsl r9, 1 - add pc, r9 - st.b r8++, r11 - st.b r8++, r11 - st.b r8++, r11 - rjmp 2b - - .size memset, . - memset diff --git a/arch/avr32/lib/strncpy_from_user.S b/arch/avr32/lib/strncpy_from_user.S deleted file mode 100644 index 72bd50599ec6..000000000000 --- a/arch/avr32/lib/strncpy_from_user.S +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copy to/from userspace with optional address space checking. - * - * Copyright 2004-2006 Atmel Corporation - * - * 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/errno.h> - -#include <asm/page.h> -#include <asm/thread_info.h> -#include <asm/asm.h> - - /* - * long strncpy_from_user(char *dst, const char *src, long count) - * - * On success, returns the length of the string, not including - * the terminating NUL. - * - * If the string is longer than count, returns count - * - * If userspace access fails, returns -EFAULT - */ - .text - .align 1 - .global strncpy_from_user - .type strncpy_from_user, "function" -strncpy_from_user: - mov r9, -EFAULT - branch_if_kernel r8, __strncpy_from_user - ret_if_privileged r8, r11, r10, r9 - - .global __strncpy_from_user - .type __strncpy_from_user, "function" -__strncpy_from_user: - cp.w r10, 0 - reteq 0 - - mov r9, r10 - -1: ld.ub r8, r11++ - st.b r12++, r8 - cp.w r8, 0 - breq 2f - sub r9, 1 - brne 1b - -2: sub r10, r9 - retal r10 - - .section .fixup, "ax" - .align 1 -3: mov r12, -EFAULT - retal r12 - - .section __ex_table, "a" - .align 2 - .long 1b, 3b diff --git a/arch/avr32/lib/strnlen_user.S b/arch/avr32/lib/strnlen_user.S deleted file mode 100644 index e46f4724962b..000000000000 --- a/arch/avr32/lib/strnlen_user.S +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copy to/from userspace with optional address space checking. - * - * Copyright 2004-2006 Atmel Corporation - * - * 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 <asm/page.h> -#include <asm/thread_info.h> -#include <asm/processor.h> -#include <asm/asm.h> - - .text - .align 1 - .global strnlen_user - .type strnlen_user, "function" -strnlen_user: - branch_if_kernel r8, __strnlen_user - sub r8, r11, 1 - add r8, r12 - retcs 0 - brmi adjust_length /* do a closer inspection */ - - .global __strnlen_user - .type __strnlen_user, "function" -__strnlen_user: - mov r10, r12 - -10: ld.ub r8, r12++ - cp.w r8, 0 - breq 2f - sub r11, 1 - brne 10b - - sub r12, -1 -2: sub r12, r10 - retal r12 - - - .type adjust_length, "function" -adjust_length: - cp.w r12, 0 /* addr must always be < TASK_SIZE */ - retmi 0 - - pushm lr - lddpc lr, _task_size - sub r11, lr, r12 - mov r9, r11 - call __strnlen_user - cp.w r12, r9 - brgt 1f - popm pc -1: popm pc, r12=0 - - .align 2 -_task_size: - .long TASK_SIZE - - .section .fixup, "ax" - .align 1 -19: retal 0 - - .section __ex_table, "a" - .align 2 - .long 10b, 19b diff --git a/arch/avr32/mach-at32ap/Kconfig b/arch/avr32/mach-at32ap/Kconfig deleted file mode 100644 index a7bbcc82058e..000000000000 --- a/arch/avr32/mach-at32ap/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -if PLATFORM_AT32AP - -menu "Atmel AVR32 AP options" - -choice - prompt "AT32AP700x static memory bus width" - depends on CPU_AT32AP700X - default AP700X_16_BIT_SMC - help - Define the width of the AP7000 external static memory interface. - This is used to determine how to mangle the address and/or data - when doing little-endian port access. - - The current code can only support a single external memory bus - width for all chip selects, excluding the flash (which is using - raw access and is thus not affected by any of this.) - -config AP700X_32_BIT_SMC - bool "32 bit" - -config AP700X_16_BIT_SMC - bool "16 bit" - -config AP700X_8_BIT_SMC - bool "8 bit" - -endchoice - -endmenu - -endif # PLATFORM_AT32AP diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile deleted file mode 100644 index fc09ec4bc725..000000000000 --- a/arch/avr32/mach-at32ap/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o -obj-y += hmatrix.o -obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o -obj-$(CONFIG_PM) += pm.o - -ifeq ($(CONFIG_PM_DEBUG),y) -CFLAGS_pm.o += -DDEBUG -endif diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c deleted file mode 100644 index 00d6dcc1d9b6..000000000000 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ /dev/null @@ -1,2368 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * 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/clk.h> -#include <linux/delay.h> -#include <linux/platform_data/dma-dw.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> -#include <linux/gpio.h> -#include <linux/spi/spi.h> -#include <linux/usb/atmel_usba_udc.h> - -#include <linux/atmel-mci.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include <mach/at32ap700x.h> -#include <mach/board.h> -#include <mach/hmatrix.h> -#include <mach/portmux.h> -#include <mach/sram.h> - -#include <sound/atmel-abdac.h> -#include <sound/atmel-ac97c.h> - -#include <video/atmel_lcdc.h> - -#include "clock.h" -#include "pio.h" -#include "pm.h" - - -#define PBMEM(base) \ - { \ - .start = base, \ - .end = base + 0x3ff, \ - .flags = IORESOURCE_MEM, \ - } -#define IRQ(num) \ - { \ - .start = num, \ - .end = num, \ - .flags = IORESOURCE_IRQ, \ - } -#define NAMED_IRQ(num, _name) \ - { \ - .start = num, \ - .end = num, \ - .name = _name, \ - .flags = IORESOURCE_IRQ, \ - } - -/* REVISIT these assume *every* device supports DMA, but several - * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more. - */ -#define DEFINE_DEV(_name, _id) \ -static u64 _name##_id##_dma_mask = DMA_BIT_MASK(32); \ -static struct platform_device _name##_id##_device = { \ - .name = #_name, \ - .id = _id, \ - .dev = { \ - .dma_mask = &_name##_id##_dma_mask, \ - .coherent_dma_mask = DMA_BIT_MASK(32), \ - }, \ - .resource = _name##_id##_resource, \ - .num_resources = ARRAY_SIZE(_name##_id##_resource), \ -} -#define DEFINE_DEV_DATA(_name, _id) \ -static u64 _name##_id##_dma_mask = DMA_BIT_MASK(32); \ -static struct platform_device _name##_id##_device = { \ - .name = #_name, \ - .id = _id, \ - .dev = { \ - .dma_mask = &_name##_id##_dma_mask, \ - .platform_data = &_name##_id##_data, \ - .coherent_dma_mask = DMA_BIT_MASK(32), \ - }, \ - .resource = _name##_id##_resource, \ - .num_resources = ARRAY_SIZE(_name##_id##_resource), \ -} - -#define select_peripheral(port, pin_mask, periph, flags) \ - at32_select_periph(GPIO_##port##_BASE, pin_mask, \ - GPIO_##periph, flags) - -#define DEV_CLK(_name, devname, bus, _index) \ -static struct clk devname##_##_name = { \ - .name = #_name, \ - .dev = &devname##_device.dev, \ - .parent = &bus##_clk, \ - .mode = bus##_clk_mode, \ - .get_rate = bus##_clk_get_rate, \ - .index = _index, \ -} - -static DEFINE_SPINLOCK(pm_lock); - -static struct clk osc0; -static struct clk osc1; - -static unsigned long osc_get_rate(struct clk *clk) -{ - return at32_board_osc_rates[clk->index]; -} - -static unsigned long pll_get_rate(struct clk *clk, unsigned long control) -{ - unsigned long div, mul, rate; - - div = PM_BFEXT(PLLDIV, control) + 1; - mul = PM_BFEXT(PLLMUL, control) + 1; - - rate = clk->parent->get_rate(clk->parent); - rate = (rate + div / 2) / div; - rate *= mul; - - return rate; -} - -static long pll_set_rate(struct clk *clk, unsigned long rate, - u32 *pll_ctrl) -{ - unsigned long mul; - unsigned long mul_best_fit = 0; - unsigned long div; - unsigned long div_min; - unsigned long div_max; - unsigned long div_best_fit = 0; - unsigned long base; - unsigned long pll_in; - unsigned long actual = 0; - unsigned long rate_error; - unsigned long rate_error_prev = ~0UL; - u32 ctrl; - - /* Rate must be between 80 MHz and 200 Mhz. */ - if (rate < 80000000UL || rate > 200000000UL) - return -EINVAL; - - ctrl = PM_BF(PLLOPT, 4); - base = clk->parent->get_rate(clk->parent); - - /* PLL input frequency must be between 6 MHz and 32 MHz. */ - div_min = DIV_ROUND_UP(base, 32000000UL); - div_max = base / 6000000UL; - - if (div_max < div_min) - return -EINVAL; - - for (div = div_min; div <= div_max; div++) { - pll_in = (base + div / 2) / div; - mul = (rate + pll_in / 2) / pll_in; - - if (mul == 0) - continue; - - actual = pll_in * mul; - rate_error = abs(actual - rate); - - if (rate_error < rate_error_prev) { - mul_best_fit = mul; - div_best_fit = div; - rate_error_prev = rate_error; - } - - if (rate_error == 0) - break; - } - - if (div_best_fit == 0) - return -EINVAL; - - ctrl |= PM_BF(PLLMUL, mul_best_fit - 1); - ctrl |= PM_BF(PLLDIV, div_best_fit - 1); - ctrl |= PM_BF(PLLCOUNT, 16); - - if (clk->parent == &osc1) - ctrl |= PM_BIT(PLLOSC); - - *pll_ctrl = ctrl; - - return actual; -} - -static unsigned long pll0_get_rate(struct clk *clk) -{ - u32 control; - - control = pm_readl(PLL0); - - return pll_get_rate(clk, control); -} - -static void pll1_mode(struct clk *clk, int enabled) -{ - unsigned long timeout; - u32 status; - u32 ctrl; - - ctrl = pm_readl(PLL1); - - if (enabled) { - if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) { - pr_debug("clk %s: failed to enable, rate not set\n", - clk->name); - return; - } - - ctrl |= PM_BIT(PLLEN); - pm_writel(PLL1, ctrl); - - /* Wait for PLL lock. */ - for (timeout = 10000; timeout; timeout--) { - status = pm_readl(ISR); - if (status & PM_BIT(LOCK1)) - break; - udelay(10); - } - - if (!(status & PM_BIT(LOCK1))) - printk(KERN_ERR "clk %s: timeout waiting for lock\n", - clk->name); - } else { - ctrl &= ~PM_BIT(PLLEN); - pm_writel(PLL1, ctrl); - } -} - -static unsigned long pll1_get_rate(struct clk *clk) -{ - u32 control; - - control = pm_readl(PLL1); - - return pll_get_rate(clk, control); -} - -static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply) -{ - u32 ctrl = 0; - unsigned long actual_rate; - - actual_rate = pll_set_rate(clk, rate, &ctrl); - - if (apply) { - if (actual_rate != rate) - return -EINVAL; - if (clk->users > 0) - return -EBUSY; - pr_debug(KERN_INFO "clk %s: new rate %lu (actual rate %lu)\n", - clk->name, rate, actual_rate); - pm_writel(PLL1, ctrl); - } - - return actual_rate; -} - -static int pll1_set_parent(struct clk *clk, struct clk *parent) -{ - u32 ctrl; - - if (clk->users > 0) - return -EBUSY; - - ctrl = pm_readl(PLL1); - WARN_ON(ctrl & PM_BIT(PLLEN)); - - if (parent == &osc0) - ctrl &= ~PM_BIT(PLLOSC); - else if (parent == &osc1) - ctrl |= PM_BIT(PLLOSC); - else - return -EINVAL; - - pm_writel(PLL1, ctrl); - clk->parent = parent; - - return 0; -} - -/* - * The AT32AP7000 has five primary clock sources: One 32kHz - * oscillator, two crystal oscillators and two PLLs. - */ -static struct clk osc32k = { - .name = "osc32k", - .get_rate = osc_get_rate, - .users = 1, - .index = 0, -}; -static struct clk osc0 = { - .name = "osc0", - .get_rate = osc_get_rate, - .users = 1, - .index = 1, -}; -static struct clk osc1 = { - .name = "osc1", - .get_rate = osc_get_rate, - .index = 2, -}; -static struct clk pll0 = { - .name = "pll0", - .get_rate = pll0_get_rate, - .parent = &osc0, -}; -static struct clk pll1 = { - .name = "pll1", - .mode = pll1_mode, - .get_rate = pll1_get_rate, - .set_rate = pll1_set_rate, - .set_parent = pll1_set_parent, - .parent = &osc0, -}; - -/* - * The main clock can be either osc0 or pll0. The boot loader may - * have chosen one for us, so we don't really know which one until we - * have a look at the SM. - */ -static struct clk *main_clock; - -/* - * Synchronous clocks are generated from the main clock. The clocks - * must satisfy the constraint - * fCPU >= fHSB >= fPB - * i.e. each clock must not be faster than its parent. - */ -static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) -{ - return main_clock->get_rate(main_clock) >> shift; -}; - -static void cpu_clk_mode(struct clk *clk, int enabled) -{ - unsigned long flags; - u32 mask; - - spin_lock_irqsave(&pm_lock, flags); - mask = pm_readl(CPU_MASK); - if (enabled) - mask |= 1 << clk->index; - else - mask &= ~(1 << clk->index); - pm_writel(CPU_MASK, mask); - spin_unlock_irqrestore(&pm_lock, flags); -} - -static unsigned long cpu_clk_get_rate(struct clk *clk) -{ - unsigned long cksel, shift = 0; - - cksel = pm_readl(CKSEL); - if (cksel & PM_BIT(CPUDIV)) - shift = PM_BFEXT(CPUSEL, cksel) + 1; - - return bus_clk_get_rate(clk, shift); -} - -static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply) -{ - u32 control; - unsigned long parent_rate, child_div, actual_rate, div; - - parent_rate = clk->parent->get_rate(clk->parent); - control = pm_readl(CKSEL); - - if (control & PM_BIT(HSBDIV)) - child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1); - else - child_div = 1; - - if (rate > 3 * (parent_rate / 4) || child_div == 1) { - actual_rate = parent_rate; - control &= ~PM_BIT(CPUDIV); - } else { - unsigned int cpusel; - div = (parent_rate + rate / 2) / rate; - if (div > child_div) - div = child_div; - cpusel = (div > 1) ? (fls(div) - 2) : 0; - control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control); - actual_rate = parent_rate / (1 << (cpusel + 1)); - } - - pr_debug("clk %s: new rate %lu (actual rate %lu)\n", - clk->name, rate, actual_rate); - - if (apply) - pm_writel(CKSEL, control); - - return actual_rate; -} - -static void hsb_clk_mode(struct clk *clk, int enabled) -{ - unsigned long flags; - u32 mask; - - spin_lock_irqsave(&pm_lock, flags); - mask = pm_readl(HSB_MASK); - if (enabled) - mask |= 1 << clk->index; - else - mask &= ~(1 << clk->index); - pm_writel(HSB_MASK, mask); - spin_unlock_irqrestore(&pm_lock, flags); -} - -static unsigned long hsb_clk_get_rate(struct clk *clk) -{ - unsigned long cksel, shift = 0; - - cksel = pm_readl(CKSEL); - if (cksel & PM_BIT(HSBDIV)) - shift = PM_BFEXT(HSBSEL, cksel) + 1; - - return bus_clk_get_rate(clk, shift); -} - -void pba_clk_mode(struct clk *clk, int enabled) -{ - unsigned long flags; - u32 mask; - - spin_lock_irqsave(&pm_lock, flags); - mask = pm_readl(PBA_MASK); - if (enabled) - mask |= 1 << clk->index; - else - mask &= ~(1 << clk->index); - pm_writel(PBA_MASK, mask); - spin_unlock_irqrestore(&pm_lock, flags); -} - -unsigned long pba_clk_get_rate(struct clk *clk) -{ - unsigned long cksel, shift = 0; - - cksel = pm_readl(CKSEL); - if (cksel & PM_BIT(PBADIV)) - shift = PM_BFEXT(PBASEL, cksel) + 1; - - return bus_clk_get_rate(clk, shift); -} - -static void pbb_clk_mode(struct clk *clk, int enabled) -{ - unsigned long flags; - u32 mask; - - spin_lock_irqsave(&pm_lock, flags); - mask = pm_readl(PBB_MASK); - if (enabled) - mask |= 1 << clk->index; - else - mask &= ~(1 << clk->index); - pm_writel(PBB_MASK, mask); - spin_unlock_irqrestore(&pm_lock, flags); -} - -static unsigned long pbb_clk_get_rate(struct clk *clk) -{ - unsigned long cksel, shift = 0; - - cksel = pm_readl(CKSEL); - if (cksel & PM_BIT(PBBDIV)) - shift = PM_BFEXT(PBBSEL, cksel) + 1; - - return bus_clk_get_rate(clk, shift); -} - -static struct clk cpu_clk = { - .name = "cpu", - .get_rate = cpu_clk_get_rate, - .set_rate = cpu_clk_set_rate, - .users = 1, -}; -static struct clk hsb_clk = { - .name = "hsb", - .parent = &cpu_clk, - .get_rate = hsb_clk_get_rate, -}; -static struct clk pba_clk = { - .name = "pba", - .parent = &hsb_clk, - .mode = hsb_clk_mode, - .get_rate = pba_clk_get_rate, - .index = 1, -}; -static struct clk pbb_clk = { - .name = "pbb", - .parent = &hsb_clk, - .mode = hsb_clk_mode, - .get_rate = pbb_clk_get_rate, - .users = 1, - .index = 2, -}; - -/* -------------------------------------------------------------------- - * Generic Clock operations - * -------------------------------------------------------------------- */ - -static void genclk_mode(struct clk *clk, int enabled) -{ - u32 control; - - control = pm_readl(GCCTRL(clk->index)); - if (enabled) - control |= PM_BIT(CEN); - else - control &= ~PM_BIT(CEN); - pm_writel(GCCTRL(clk->index), control); -} - -static unsigned long genclk_get_rate(struct clk *clk) -{ - u32 control; - unsigned long div = 1; - - control = pm_readl(GCCTRL(clk->index)); - if (control & PM_BIT(DIVEN)) - div = 2 * (PM_BFEXT(DIV, control) + 1); - - return clk->parent->get_rate(clk->parent) / div; -} - -static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) -{ - u32 control; - unsigned long parent_rate, actual_rate, div; - - parent_rate = clk->parent->get_rate(clk->parent); - control = pm_readl(GCCTRL(clk->index)); - - if (rate > 3 * parent_rate / 4) { - actual_rate = parent_rate; - control &= ~PM_BIT(DIVEN); - } else { - div = (parent_rate + rate) / (2 * rate) - 1; - control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN); - actual_rate = parent_rate / (2 * (div + 1)); - } - - dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n", - clk->name, rate, actual_rate); - - if (apply) - pm_writel(GCCTRL(clk->index), control); - - return actual_rate; -} - -int genclk_set_parent(struct clk *clk, struct clk *parent) -{ - u32 control; - - dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n", - clk->name, parent->name, clk->parent->name); - - control = pm_readl(GCCTRL(clk->index)); - - if (parent == &osc1 || parent == &pll1) - control |= PM_BIT(OSCSEL); - else if (parent == &osc0 || parent == &pll0) - control &= ~PM_BIT(OSCSEL); - else - return -EINVAL; - - if (parent == &pll0 || parent == &pll1) - control |= PM_BIT(PLLSEL); - else - control &= ~PM_BIT(PLLSEL); - - pm_writel(GCCTRL(clk->index), control); - clk->parent = parent; - - return 0; -} - -static void __init genclk_init_parent(struct clk *clk) -{ - u32 control; - struct clk *parent; - - BUG_ON(clk->index > 7); - - control = pm_readl(GCCTRL(clk->index)); - if (control & PM_BIT(OSCSEL)) - parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1; - else - parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0; - - clk->parent = parent; -} - -static struct resource dw_dmac0_resource[] = { - PBMEM(0xff200000), - IRQ(2), -}; -DEFINE_DEV(dw_dmac, 0); -DEV_CLK(hclk, dw_dmac0, hsb, 10); - -/* -------------------------------------------------------------------- - * System peripherals - * -------------------------------------------------------------------- */ -static struct resource at32_pm0_resource[] = { - { - .start = 0xfff00000, - .end = 0xfff0007f, - .flags = IORESOURCE_MEM, - }, - IRQ(20), -}; - -static struct resource at32ap700x_rtc0_resource[] = { - { - .start = 0xfff00080, - .end = 0xfff000af, - .flags = IORESOURCE_MEM, - }, - IRQ(21), -}; - -static struct resource at32_wdt0_resource[] = { - { - .start = 0xfff000b0, - .end = 0xfff000cf, - .flags = IORESOURCE_MEM, - }, -}; - -static struct resource at32_eic0_resource[] = { - { - .start = 0xfff00100, - .end = 0xfff0013f, - .flags = IORESOURCE_MEM, - }, - IRQ(19), -}; - -DEFINE_DEV(at32_pm, 0); -DEFINE_DEV(at32ap700x_rtc, 0); -DEFINE_DEV(at32_wdt, 0); -DEFINE_DEV(at32_eic, 0); - -/* - * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this - * is always running. - */ -static struct clk at32_pm_pclk = { - .name = "pclk", - .dev = &at32_pm0_device.dev, - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .users = 1, - .index = 0, -}; - -static struct resource intc0_resource[] = { - PBMEM(0xfff00400), -}; -struct platform_device at32_intc0_device = { - .name = "intc", - .id = 0, - .resource = intc0_resource, - .num_resources = ARRAY_SIZE(intc0_resource), -}; -DEV_CLK(pclk, at32_intc0, pbb, 1); - -static struct clk ebi_clk = { - .name = "ebi", - .parent = &hsb_clk, - .mode = hsb_clk_mode, - .get_rate = hsb_clk_get_rate, - .users = 1, -}; -static struct clk hramc_clk = { - .name = "hramc", - .parent = &hsb_clk, - .mode = hsb_clk_mode, - .get_rate = hsb_clk_get_rate, - .users = 1, - .index = 3, -}; -static struct clk sdramc_clk = { - .name = "sdramc_clk", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .users = 1, - .index = 14, -}; - -static struct resource smc0_resource[] = { - PBMEM(0xfff03400), -}; -DEFINE_DEV(smc, 0); -DEV_CLK(pclk, smc0, pbb, 13); -DEV_CLK(mck, smc0, hsb, 0); - -static struct platform_device pdc_device = { - .name = "pdc", - .id = 0, -}; -DEV_CLK(hclk, pdc, hsb, 4); -DEV_CLK(pclk, pdc, pba, 16); - -static struct clk pico_clk = { - .name = "pico", - .parent = &cpu_clk, - .mode = cpu_clk_mode, - .get_rate = cpu_clk_get_rate, - .users = 1, -}; - -/* -------------------------------------------------------------------- - * HMATRIX - * -------------------------------------------------------------------- */ - -struct clk at32_hmatrix_clk = { - .name = "hmatrix_clk", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .index = 2, - .users = 1, -}; - -/* - * Set bits in the HMATRIX Special Function Register (SFR) used by the - * External Bus Interface (EBI). This can be used to enable special - * features like CompactFlash support, NAND Flash support, etc. on - * certain chipselects. - */ -static inline void set_ebi_sfr_bits(u32 mask) -{ - hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, mask); -} - -/* -------------------------------------------------------------------- - * Timer/Counter (TC) - * -------------------------------------------------------------------- */ - -static struct resource at32_tcb0_resource[] = { - PBMEM(0xfff00c00), - IRQ(22), -}; -static struct platform_device at32_tcb0_device = { - .name = "atmel_tcb", - .id = 0, - .resource = at32_tcb0_resource, - .num_resources = ARRAY_SIZE(at32_tcb0_resource), -}; -DEV_CLK(t0_clk, at32_tcb0, pbb, 3); - -static struct resource at32_tcb1_resource[] = { - PBMEM(0xfff01000), - IRQ(23), -}; -static struct platform_device at32_tcb1_device = { - .name = "atmel_tcb", - .id = 1, - .resource = at32_tcb1_resource, - .num_resources = ARRAY_SIZE(at32_tcb1_resource), -}; -DEV_CLK(t0_clk, at32_tcb1, pbb, 4); - -/* -------------------------------------------------------------------- - * PIO - * -------------------------------------------------------------------- */ - -static struct resource pio0_resource[] = { - PBMEM(0xffe02800), - IRQ(13), -}; -DEFINE_DEV(pio, 0); -DEV_CLK(mck, pio0, pba, 10); - -static struct resource pio1_resource[] = { - PBMEM(0xffe02c00), - IRQ(14), -}; -DEFINE_DEV(pio, 1); -DEV_CLK(mck, pio1, pba, 11); - -static struct resource pio2_resource[] = { - PBMEM(0xffe03000), - IRQ(15), -}; -DEFINE_DEV(pio, 2); -DEV_CLK(mck, pio2, pba, 12); - -static struct resource pio3_resource[] = { - PBMEM(0xffe03400), - IRQ(16), -}; -DEFINE_DEV(pio, 3); -DEV_CLK(mck, pio3, pba, 13); - -static struct resource pio4_resource[] = { - PBMEM(0xffe03800), - IRQ(17), -}; -DEFINE_DEV(pio, 4); -DEV_CLK(mck, pio4, pba, 14); - -static int __init system_device_init(void) -{ - platform_device_register(&at32_pm0_device); - platform_device_register(&at32_intc0_device); - platform_device_register(&at32ap700x_rtc0_device); - platform_device_register(&at32_wdt0_device); - platform_device_register(&at32_eic0_device); - platform_device_register(&smc0_device); - platform_device_register(&pdc_device); - platform_device_register(&dw_dmac0_device); - - platform_device_register(&at32_tcb0_device); - platform_device_register(&at32_tcb1_device); - - platform_device_register(&pio0_device); - platform_device_register(&pio1_device); - platform_device_register(&pio2_device); - platform_device_register(&pio3_device); - platform_device_register(&pio4_device); - - return 0; -} -core_initcall(system_device_init); - -/* -------------------------------------------------------------------- - * PSIF - * -------------------------------------------------------------------- */ -static struct resource atmel_psif0_resource[] __initdata = { - { - .start = 0xffe03c00, - .end = 0xffe03cff, - .flags = IORESOURCE_MEM, - }, - IRQ(18), -}; -static struct clk atmel_psif0_pclk = { - .name = "pclk", - .parent = &pba_clk, - .mode = pba_clk_mode, - .get_rate = pba_clk_get_rate, - .index = 15, -}; - -static struct resource atmel_psif1_resource[] __initdata = { - { - .start = 0xffe03d00, - .end = 0xffe03dff, - .flags = IORESOURCE_MEM, - }, - IRQ(18), -}; -static struct clk atmel_psif1_pclk = { - .name = "pclk", - .parent = &pba_clk, - .mode = pba_clk_mode, - .get_rate = pba_clk_get_rate, - .index = 15, -}; - -struct platform_device *__init at32_add_device_psif(unsigned int id) -{ - struct platform_device *pdev; - u32 pin_mask; - - if (!(id == 0 || id == 1)) - return NULL; - - pdev = platform_device_alloc("atmel_psif", id); - if (!pdev) - return NULL; - - switch (id) { - case 0: - pin_mask = (1 << 8) | (1 << 9); /* CLOCK & DATA */ - - if (platform_device_add_resources(pdev, atmel_psif0_resource, - ARRAY_SIZE(atmel_psif0_resource))) - goto err_add_resources; - atmel_psif0_pclk.dev = &pdev->dev; - select_peripheral(PIOA, pin_mask, PERIPH_A, 0); - break; - case 1: - pin_mask = (1 << 11) | (1 << 12); /* CLOCK & DATA */ - - if (platform_device_add_resources(pdev, atmel_psif1_resource, - ARRAY_SIZE(atmel_psif1_resource))) - goto err_add_resources; - atmel_psif1_pclk.dev = &pdev->dev; - select_peripheral(PIOB, pin_mask, PERIPH_A, 0); - break; - default: - return NULL; - } - - platform_device_add(pdev); - return pdev; - -err_add_resources: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * USART - * -------------------------------------------------------------------- */ - -static struct atmel_uart_data atmel_usart0_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; -static struct resource atmel_usart0_resource[] = { - PBMEM(0xffe00c00), - IRQ(6), -}; -DEFINE_DEV_DATA(atmel_usart, 0); -DEV_CLK(usart, atmel_usart0, pba, 3); - -static struct atmel_uart_data atmel_usart1_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; -static struct resource atmel_usart1_resource[] = { - PBMEM(0xffe01000), - IRQ(7), -}; -DEFINE_DEV_DATA(atmel_usart, 1); -DEV_CLK(usart, atmel_usart1, pba, 4); - -static struct atmel_uart_data atmel_usart2_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; -static struct resource atmel_usart2_resource[] = { - PBMEM(0xffe01400), - IRQ(8), -}; -DEFINE_DEV_DATA(atmel_usart, 2); -DEV_CLK(usart, atmel_usart2, pba, 5); - -static struct atmel_uart_data atmel_usart3_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; -static struct resource atmel_usart3_resource[] = { - PBMEM(0xffe01800), - IRQ(9), -}; -DEFINE_DEV_DATA(atmel_usart, 3); -DEV_CLK(usart, atmel_usart3, pba, 6); - -static inline void configure_usart0_pins(int flags) -{ - u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */ - if (flags & ATMEL_USART_RTS) pin_mask |= (1 << 6); - if (flags & ATMEL_USART_CTS) pin_mask |= (1 << 7); - if (flags & ATMEL_USART_CLK) pin_mask |= (1 << 10); - - select_peripheral(PIOA, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP); -} - -static inline void configure_usart1_pins(int flags) -{ - u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */ - if (flags & ATMEL_USART_RTS) pin_mask |= (1 << 19); - if (flags & ATMEL_USART_CTS) pin_mask |= (1 << 20); - if (flags & ATMEL_USART_CLK) pin_mask |= (1 << 16); - - select_peripheral(PIOA, pin_mask, PERIPH_A, AT32_GPIOF_PULLUP); -} - -static inline void configure_usart2_pins(int flags) -{ - u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */ - if (flags & ATMEL_USART_RTS) pin_mask |= (1 << 30); - if (flags & ATMEL_USART_CTS) pin_mask |= (1 << 29); - if (flags & ATMEL_USART_CLK) pin_mask |= (1 << 28); - - select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP); -} - -static inline void configure_usart3_pins(int flags) -{ - u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */ - if (flags & ATMEL_USART_RTS) pin_mask |= (1 << 16); - if (flags & ATMEL_USART_CTS) pin_mask |= (1 << 15); - if (flags & ATMEL_USART_CLK) pin_mask |= (1 << 19); - - select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP); -} - -static struct platform_device *__initdata at32_usarts[4]; - -void __init at32_map_usart(unsigned int hw_id, unsigned int line, int flags) -{ - struct platform_device *pdev; - struct atmel_uart_data *pdata; - - switch (hw_id) { - case 0: - pdev = &atmel_usart0_device; - configure_usart0_pins(flags); - break; - case 1: - pdev = &atmel_usart1_device; - configure_usart1_pins(flags); - break; - case 2: - pdev = &atmel_usart2_device; - configure_usart2_pins(flags); - break; - case 3: - pdev = &atmel_usart3_device; - configure_usart3_pins(flags); - break; - default: - return; - } - - if (PXSEG(pdev->resource[0].start) == P4SEG) { - /* Addresses in the P4 segment are permanently mapped 1:1 */ - struct atmel_uart_data *data = pdev->dev.platform_data; - data->regs = (void __iomem *)pdev->resource[0].start; - } - - pdev->id = line; - pdata = pdev->dev.platform_data; - pdata->num = line; - at32_usarts[line] = pdev; -} - -struct platform_device *__init at32_add_device_usart(unsigned int id) -{ - platform_device_register(at32_usarts[id]); - return at32_usarts[id]; -} - -void __init at32_setup_serial_console(unsigned int usart_id) -{ -#ifdef CONFIG_SERIAL_ATMEL - atmel_default_console_device = at32_usarts[usart_id]; -#endif -} - -/* -------------------------------------------------------------------- - * Ethernet - * -------------------------------------------------------------------- */ - -#ifdef CONFIG_CPU_AT32AP7000 -static struct macb_platform_data macb0_data; -static struct resource macb0_resource[] = { - PBMEM(0xfff01800), - IRQ(25), -}; -DEFINE_DEV_DATA(macb, 0); -DEV_CLK(hclk, macb0, hsb, 8); -DEV_CLK(pclk, macb0, pbb, 6); - -static struct macb_platform_data macb1_data; -static struct resource macb1_resource[] = { - PBMEM(0xfff01c00), - IRQ(26), -}; -DEFINE_DEV_DATA(macb, 1); -DEV_CLK(hclk, macb1, hsb, 9); -DEV_CLK(pclk, macb1, pbb, 7); - -struct platform_device *__init -at32_add_device_eth(unsigned int id, struct macb_platform_data *data) -{ - struct platform_device *pdev; - u32 pin_mask; - - switch (id) { - case 0: - pdev = &macb0_device; - - pin_mask = (1 << 3); /* TXD0 */ - pin_mask |= (1 << 4); /* TXD1 */ - pin_mask |= (1 << 7); /* TXEN */ - pin_mask |= (1 << 8); /* TXCK */ - pin_mask |= (1 << 9); /* RXD0 */ - pin_mask |= (1 << 10); /* RXD1 */ - pin_mask |= (1 << 13); /* RXER */ - pin_mask |= (1 << 15); /* RXDV */ - pin_mask |= (1 << 16); /* MDC */ - pin_mask |= (1 << 17); /* MDIO */ - - if (!data->is_rmii) { - pin_mask |= (1 << 0); /* COL */ - pin_mask |= (1 << 1); /* CRS */ - pin_mask |= (1 << 2); /* TXER */ - pin_mask |= (1 << 5); /* TXD2 */ - pin_mask |= (1 << 6); /* TXD3 */ - pin_mask |= (1 << 11); /* RXD2 */ - pin_mask |= (1 << 12); /* RXD3 */ - pin_mask |= (1 << 14); /* RXCK */ -#ifndef CONFIG_BOARD_MIMC200 - pin_mask |= (1 << 18); /* SPD */ -#endif - } - - select_peripheral(PIOC, pin_mask, PERIPH_A, 0); - - break; - - case 1: - pdev = &macb1_device; - - pin_mask = (1 << 13); /* TXD0 */ - pin_mask |= (1 << 14); /* TXD1 */ - pin_mask |= (1 << 11); /* TXEN */ - pin_mask |= (1 << 12); /* TXCK */ - pin_mask |= (1 << 10); /* RXD0 */ - pin_mask |= (1 << 6); /* RXD1 */ - pin_mask |= (1 << 5); /* RXER */ - pin_mask |= (1 << 4); /* RXDV */ - pin_mask |= (1 << 3); /* MDC */ - pin_mask |= (1 << 2); /* MDIO */ - -#ifndef CONFIG_BOARD_MIMC200 - if (!data->is_rmii) - pin_mask |= (1 << 15); /* SPD */ -#endif - - select_peripheral(PIOD, pin_mask, PERIPH_B, 0); - - if (!data->is_rmii) { - pin_mask = (1 << 19); /* COL */ - pin_mask |= (1 << 23); /* CRS */ - pin_mask |= (1 << 26); /* TXER */ - pin_mask |= (1 << 27); /* TXD2 */ - pin_mask |= (1 << 28); /* TXD3 */ - pin_mask |= (1 << 29); /* RXD2 */ - pin_mask |= (1 << 30); /* RXD3 */ - pin_mask |= (1 << 24); /* RXCK */ - - select_peripheral(PIOC, pin_mask, PERIPH_B, 0); - } - break; - - default: - return NULL; - } - - memcpy(pdev->dev.platform_data, data, sizeof(struct macb_platform_data)); - platform_device_register(pdev); - - return pdev; -} -#endif - -/* -------------------------------------------------------------------- - * SPI - * -------------------------------------------------------------------- */ -static struct resource atmel_spi0_resource[] = { - PBMEM(0xffe00000), - IRQ(3), -}; -DEFINE_DEV(atmel_spi, 0); -DEV_CLK(spi_clk, atmel_spi0, pba, 0); - -static struct resource atmel_spi1_resource[] = { - PBMEM(0xffe00400), - IRQ(4), -}; -DEFINE_DEV(atmel_spi, 1); -DEV_CLK(spi_clk, atmel_spi1, pba, 1); - -void __init -at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n) -{ - /* - * Manage the chipselects as GPIOs, normally using the same pins - * the SPI controller expects; but boards can use other pins. - */ - static u8 __initdata spi_pins[][4] = { - { GPIO_PIN_PA(3), GPIO_PIN_PA(4), - GPIO_PIN_PA(5), GPIO_PIN_PA(20) }, - { GPIO_PIN_PB(2), GPIO_PIN_PB(3), - GPIO_PIN_PB(4), GPIO_PIN_PA(27) }, - }; - unsigned int pin, mode; - - /* There are only 2 SPI controllers */ - if (bus_num > 1) - return; - - for (; n; n--, b++) { - b->bus_num = bus_num; - if (b->chip_select >= 4) - continue; - pin = (unsigned)b->controller_data; - if (!pin) { - pin = spi_pins[bus_num][b->chip_select]; - b->controller_data = (void *)pin; - } - mode = AT32_GPIOF_OUTPUT; - if (!(b->mode & SPI_CS_HIGH)) - mode |= AT32_GPIOF_HIGH; - at32_select_gpio(pin, mode); - } -} - -struct platform_device *__init -at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) -{ - struct platform_device *pdev; - u32 pin_mask; - - switch (id) { - case 0: - pdev = &atmel_spi0_device; - pin_mask = (1 << 1) | (1 << 2); /* MOSI & SCK */ - - /* pullup MISO so a level is always defined */ - select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP); - select_peripheral(PIOA, pin_mask, PERIPH_A, 0); - - at32_spi_setup_slaves(0, b, n); - break; - - case 1: - pdev = &atmel_spi1_device; - pin_mask = (1 << 1) | (1 << 5); /* MOSI */ - - /* pullup MISO so a level is always defined */ - select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP); - select_peripheral(PIOB, pin_mask, PERIPH_B, 0); - - at32_spi_setup_slaves(1, b, n); - break; - - default: - return NULL; - } - - spi_register_board_info(b, n); - platform_device_register(pdev); - return pdev; -} - -/* -------------------------------------------------------------------- - * TWI - * -------------------------------------------------------------------- */ -static struct resource atmel_twi0_resource[] __initdata = { - PBMEM(0xffe00800), - IRQ(5), -}; -static struct clk atmel_twi0_pclk = { - .name = "twi_pclk", - .parent = &pba_clk, - .mode = pba_clk_mode, - .get_rate = pba_clk_get_rate, - .index = 2, -}; - -struct platform_device *__init at32_add_device_twi(unsigned int id, - struct i2c_board_info *b, - unsigned int n) -{ - struct platform_device *pdev; - u32 pin_mask; - - if (id != 0) - return NULL; - - pdev = platform_device_alloc("atmel_twi", id); - if (!pdev) - return NULL; - - if (platform_device_add_resources(pdev, atmel_twi0_resource, - ARRAY_SIZE(atmel_twi0_resource))) - goto err_add_resources; - - pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */ - - select_peripheral(PIOA, pin_mask, PERIPH_A, 0); - - atmel_twi0_pclk.dev = &pdev->dev; - - if (b) - i2c_register_board_info(id, b, n); - - platform_device_add(pdev); - return pdev; - -err_add_resources: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * MMC - * -------------------------------------------------------------------- */ -static struct resource atmel_mci0_resource[] __initdata = { - PBMEM(0xfff02400), - IRQ(28), -}; -static struct clk atmel_mci0_pclk = { - .name = "mci_clk", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .index = 9, -}; - -static bool at32_mci_dma_filter(struct dma_chan *chan, void *pdata) -{ - struct dw_dma_slave *sl = pdata; - - if (!sl) - return false; - - if (sl->dma_dev == chan->device->dev) { - chan->private = sl; - return true; - } - - return false; -} - -struct platform_device *__init -at32_add_device_mci(unsigned int id, struct mci_platform_data *data) -{ - struct platform_device *pdev; - struct dw_dma_slave *slave; - u32 pioa_mask; - u32 piob_mask; - - if (id != 0 || !data) - return NULL; - - /* Must have at least one usable slot */ - if (!data->slot[0].bus_width && !data->slot[1].bus_width) - return NULL; - - pdev = platform_device_alloc("atmel_mci", id); - if (!pdev) - goto fail; - - if (platform_device_add_resources(pdev, atmel_mci0_resource, - ARRAY_SIZE(atmel_mci0_resource))) - goto fail; - - slave = kzalloc(sizeof(*slave), GFP_KERNEL); - if (!slave) - goto fail; - - slave->dma_dev = &dw_dmac0_device.dev; - slave->src_id = 0; - slave->dst_id = 1; - slave->m_master = 1; - slave->p_master = 0; - - data->dma_slave = slave; - data->dma_filter = at32_mci_dma_filter; - - if (platform_device_add_data(pdev, data, - sizeof(struct mci_platform_data))) - goto fail_free; - - /* CLK line is common to both slots */ - pioa_mask = 1 << 10; - - switch (data->slot[0].bus_width) { - case 4: - pioa_mask |= 1 << 13; /* DATA1 */ - pioa_mask |= 1 << 14; /* DATA2 */ - pioa_mask |= 1 << 15; /* DATA3 */ - /* fall through */ - case 1: - pioa_mask |= 1 << 11; /* CMD */ - pioa_mask |= 1 << 12; /* DATA0 */ - - if (gpio_is_valid(data->slot[0].detect_pin)) - at32_select_gpio(data->slot[0].detect_pin, 0); - if (gpio_is_valid(data->slot[0].wp_pin)) - at32_select_gpio(data->slot[0].wp_pin, 0); - break; - case 0: - /* Slot is unused */ - break; - default: - goto fail_free; - } - - select_peripheral(PIOA, pioa_mask, PERIPH_A, 0); - piob_mask = 0; - - switch (data->slot[1].bus_width) { - case 4: - piob_mask |= 1 << 8; /* DATA1 */ - piob_mask |= 1 << 9; /* DATA2 */ - piob_mask |= 1 << 10; /* DATA3 */ - /* fall through */ - case 1: - piob_mask |= 1 << 6; /* CMD */ - piob_mask |= 1 << 7; /* DATA0 */ - select_peripheral(PIOB, piob_mask, PERIPH_B, 0); - - if (gpio_is_valid(data->slot[1].detect_pin)) - at32_select_gpio(data->slot[1].detect_pin, 0); - if (gpio_is_valid(data->slot[1].wp_pin)) - at32_select_gpio(data->slot[1].wp_pin, 0); - break; - case 0: - /* Slot is unused */ - break; - default: - if (!data->slot[0].bus_width) - goto fail_free; - - data->slot[1].bus_width = 0; - break; - } - - atmel_mci0_pclk.dev = &pdev->dev; - - platform_device_add(pdev); - return pdev; - -fail_free: - kfree(slave); -fail: - data->dma_slave = NULL; - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * LCDC - * -------------------------------------------------------------------- */ -#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) -static struct atmel_lcdfb_pdata atmel_lcdfb0_data; -static struct resource atmel_lcdfb0_resource[] = { - { - .start = 0xff000000, - .end = 0xff000fff, - .flags = IORESOURCE_MEM, - }, - IRQ(1), - { - /* Placeholder for pre-allocated fb memory */ - .start = 0x00000000, - .end = 0x00000000, - .flags = 0, - }, -}; -DEFINE_DEV_DATA(atmel_lcdfb, 0); -DEV_CLK(hclk, atmel_lcdfb0, hsb, 7); -static struct clk atmel_lcdfb0_pixclk = { - .name = "lcdc_clk", - .dev = &atmel_lcdfb0_device.dev, - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 7, -}; - -struct platform_device *__init -at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data, - unsigned long fbmem_start, unsigned long fbmem_len, - u64 pin_mask) -{ - struct platform_device *pdev; - struct atmel_lcdfb_pdata *info; - struct fb_monspecs *monspecs; - struct fb_videomode *modedb; - unsigned int modedb_size; - u32 portc_mask, portd_mask, porte_mask; - - /* - * Do a deep copy of the fb data, monspecs and modedb. Make - * sure all allocations are done before setting up the - * portmux. - */ - monspecs = kmemdup(data->default_monspecs, - sizeof(struct fb_monspecs), GFP_KERNEL); - if (!monspecs) - return NULL; - - modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len; - modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL); - if (!modedb) - goto err_dup_modedb; - monspecs->modedb = modedb; - - switch (id) { - case 0: - pdev = &atmel_lcdfb0_device; - - if (pin_mask == 0ULL) - /* Default to "full" lcdc control signals and 24bit */ - pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL; - - /* LCDC on port C */ - portc_mask = pin_mask & 0xfff80000; - select_peripheral(PIOC, portc_mask, PERIPH_A, 0); - - /* LCDC on port D */ - portd_mask = pin_mask & 0x0003ffff; - select_peripheral(PIOD, portd_mask, PERIPH_A, 0); - - /* LCDC on port E */ - porte_mask = (pin_mask >> 32) & 0x0007ffff; - select_peripheral(PIOE, porte_mask, PERIPH_B, 0); - - clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); - clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); - break; - - default: - goto err_invalid_id; - } - - if (fbmem_len) { - pdev->resource[2].start = fbmem_start; - pdev->resource[2].end = fbmem_start + fbmem_len - 1; - pdev->resource[2].flags = IORESOURCE_MEM; - } - - info = pdev->dev.platform_data; - memcpy(info, data, sizeof(struct atmel_lcdfb_pdata)); - info->default_monspecs = monspecs; - - pdev->name = "at32ap-lcdfb"; - - platform_device_register(pdev); - return pdev; - -err_invalid_id: - kfree(modedb); -err_dup_modedb: - kfree(monspecs); - return NULL; -} -#endif - -/* -------------------------------------------------------------------- - * PWM - * -------------------------------------------------------------------- */ -static struct resource atmel_pwm0_resource[] __initdata = { - PBMEM(0xfff01400), - IRQ(24), -}; -static struct clk atmel_pwm0_mck = { - .name = "at91sam9rl-pwm", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .index = 5, -}; - -struct platform_device *__init at32_add_device_pwm(u32 mask) -{ - struct platform_device *pdev; - u32 pin_mask; - - if (!mask) - return NULL; - - pdev = platform_device_alloc("at91sam9rl-pwm", 0); - if (!pdev) - return NULL; - - if (platform_device_add_resources(pdev, atmel_pwm0_resource, - ARRAY_SIZE(atmel_pwm0_resource))) - goto out_free_pdev; - - pin_mask = 0; - if (mask & (1 << 0)) - pin_mask |= (1 << 28); - if (mask & (1 << 1)) - pin_mask |= (1 << 29); - if (pin_mask > 0) - select_peripheral(PIOA, pin_mask, PERIPH_A, 0); - - pin_mask = 0; - if (mask & (1 << 2)) - pin_mask |= (1 << 21); - if (mask & (1 << 3)) - pin_mask |= (1 << 22); - if (pin_mask > 0) - select_peripheral(PIOA, pin_mask, PERIPH_B, 0); - - atmel_pwm0_mck.dev = &pdev->dev; - - platform_device_add(pdev); - - return pdev; - -out_free_pdev: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * SSC - * -------------------------------------------------------------------- */ -static struct resource ssc0_resource[] = { - PBMEM(0xffe01c00), - IRQ(10), -}; -DEFINE_DEV(ssc, 0); -DEV_CLK(pclk, ssc0, pba, 7); - -static struct resource ssc1_resource[] = { - PBMEM(0xffe02000), - IRQ(11), -}; -DEFINE_DEV(ssc, 1); -DEV_CLK(pclk, ssc1, pba, 8); - -static struct resource ssc2_resource[] = { - PBMEM(0xffe02400), - IRQ(12), -}; -DEFINE_DEV(ssc, 2); -DEV_CLK(pclk, ssc2, pba, 9); - -struct platform_device *__init -at32_add_device_ssc(unsigned int id, unsigned int flags) -{ - struct platform_device *pdev; - u32 pin_mask = 0; - - switch (id) { - case 0: - pdev = &ssc0_device; - if (flags & ATMEL_SSC_RF) - pin_mask |= (1 << 21); /* RF */ - if (flags & ATMEL_SSC_RK) - pin_mask |= (1 << 22); /* RK */ - if (flags & ATMEL_SSC_TK) - pin_mask |= (1 << 23); /* TK */ - if (flags & ATMEL_SSC_TF) - pin_mask |= (1 << 24); /* TF */ - if (flags & ATMEL_SSC_TD) - pin_mask |= (1 << 25); /* TD */ - if (flags & ATMEL_SSC_RD) - pin_mask |= (1 << 26); /* RD */ - - if (pin_mask > 0) - select_peripheral(PIOA, pin_mask, PERIPH_A, 0); - - break; - case 1: - pdev = &ssc1_device; - if (flags & ATMEL_SSC_RF) - pin_mask |= (1 << 0); /* RF */ - if (flags & ATMEL_SSC_RK) - pin_mask |= (1 << 1); /* RK */ - if (flags & ATMEL_SSC_TK) - pin_mask |= (1 << 2); /* TK */ - if (flags & ATMEL_SSC_TF) - pin_mask |= (1 << 3); /* TF */ - if (flags & ATMEL_SSC_TD) - pin_mask |= (1 << 4); /* TD */ - if (flags & ATMEL_SSC_RD) - pin_mask |= (1 << 5); /* RD */ - - if (pin_mask > 0) - select_peripheral(PIOA, pin_mask, PERIPH_B, 0); - - break; - case 2: - pdev = &ssc2_device; - if (flags & ATMEL_SSC_TD) - pin_mask |= (1 << 13); /* TD */ - if (flags & ATMEL_SSC_RD) - pin_mask |= (1 << 14); /* RD */ - if (flags & ATMEL_SSC_TK) - pin_mask |= (1 << 15); /* TK */ - if (flags & ATMEL_SSC_TF) - pin_mask |= (1 << 16); /* TF */ - if (flags & ATMEL_SSC_RF) - pin_mask |= (1 << 17); /* RF */ - if (flags & ATMEL_SSC_RK) - pin_mask |= (1 << 18); /* RK */ - - if (pin_mask > 0) - select_peripheral(PIOB, pin_mask, PERIPH_A, 0); - - break; - default: - return NULL; - } - - platform_device_register(pdev); - return pdev; -} - -/* -------------------------------------------------------------------- - * USB Device Controller - * -------------------------------------------------------------------- */ -static struct resource usba0_resource[] __initdata = { - { - .start = 0xff300000, - .end = 0xff3fffff, - .flags = IORESOURCE_MEM, - }, { - .start = 0xfff03000, - .end = 0xfff033ff, - .flags = IORESOURCE_MEM, - }, - IRQ(31), -}; -static struct clk usba0_pclk = { - .name = "pclk", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .index = 12, -}; -static struct clk usba0_hclk = { - .name = "hclk", - .parent = &hsb_clk, - .mode = hsb_clk_mode, - .get_rate = hsb_clk_get_rate, - .index = 6, -}; - -#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ - [idx] = { \ - .name = nam, \ - .index = idx, \ - .fifo_size = maxpkt, \ - .nr_banks = maxbk, \ - .can_dma = dma, \ - .can_isoc = isoc, \ - } - -static struct usba_ep_data at32_usba_ep[] __initdata = { - EP("ep0", 0, 64, 1, 0, 0), - EP("ep1", 1, 512, 2, 1, 1), - EP("ep2", 2, 512, 2, 1, 1), - EP("ep3-int", 3, 64, 3, 1, 0), - EP("ep4-int", 4, 64, 3, 1, 0), - EP("ep5", 5, 1024, 3, 1, 1), - EP("ep6", 6, 1024, 3, 1, 1), -}; - -#undef EP - -struct platform_device *__init -at32_add_device_usba(unsigned int id, struct usba_platform_data *data) -{ - /* - * pdata doesn't have room for any endpoints, so we need to - * append room for the ones we need right after it. - */ - struct { - struct usba_platform_data pdata; - struct usba_ep_data ep[7]; - } usba_data; - struct platform_device *pdev; - - if (id != 0) - return NULL; - - pdev = platform_device_alloc("atmel_usba_udc", 0); - if (!pdev) - return NULL; - - if (platform_device_add_resources(pdev, usba0_resource, - ARRAY_SIZE(usba0_resource))) - goto out_free_pdev; - - if (data) { - usba_data.pdata.vbus_pin = data->vbus_pin; - usba_data.pdata.vbus_pin_inverted = data->vbus_pin_inverted; - } else { - usba_data.pdata.vbus_pin = -EINVAL; - usba_data.pdata.vbus_pin_inverted = -EINVAL; - } - - data = &usba_data.pdata; - data->num_ep = ARRAY_SIZE(at32_usba_ep); - memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep)); - - if (platform_device_add_data(pdev, data, sizeof(usba_data))) - goto out_free_pdev; - - if (gpio_is_valid(data->vbus_pin)) - at32_select_gpio(data->vbus_pin, 0); - - usba0_pclk.dev = &pdev->dev; - usba0_hclk.dev = &pdev->dev; - - platform_device_add(pdev); - - return pdev; - -out_free_pdev: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * IDE / CompactFlash - * -------------------------------------------------------------------- */ -#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7001) -static struct resource at32_smc_cs4_resource[] __initdata = { - { - .start = 0x04000000, - .end = 0x07ffffff, - .flags = IORESOURCE_MEM, - }, - IRQ(~0UL), /* Magic IRQ will be overridden */ -}; -static struct resource at32_smc_cs5_resource[] __initdata = { - { - .start = 0x20000000, - .end = 0x23ffffff, - .flags = IORESOURCE_MEM, - }, - IRQ(~0UL), /* Magic IRQ will be overridden */ -}; - -static int __init at32_init_ide_or_cf(struct platform_device *pdev, - unsigned int cs, unsigned int extint) -{ - static unsigned int extint_pin_map[4] __initdata = { - (1 << 25), - (1 << 26), - (1 << 27), - (1 << 28), - }; - static bool common_pins_initialized __initdata = false; - unsigned int extint_pin; - int ret; - u32 pin_mask; - - if (extint >= ARRAY_SIZE(extint_pin_map)) - return -EINVAL; - extint_pin = extint_pin_map[extint]; - - switch (cs) { - case 4: - ret = platform_device_add_resources(pdev, - at32_smc_cs4_resource, - ARRAY_SIZE(at32_smc_cs4_resource)); - if (ret) - return ret; - - /* NCS4 -> OE_N */ - select_peripheral(PIOE, (1 << 21), PERIPH_A, 0); - hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE); - break; - case 5: - ret = platform_device_add_resources(pdev, - at32_smc_cs5_resource, - ARRAY_SIZE(at32_smc_cs5_resource)); - if (ret) - return ret; - - /* NCS5 -> OE_N */ - select_peripheral(PIOE, (1 << 22), PERIPH_A, 0); - hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE); - break; - default: - return -EINVAL; - } - - if (!common_pins_initialized) { - pin_mask = (1 << 19); /* CFCE1 -> CS0_N */ - pin_mask |= (1 << 20); /* CFCE2 -> CS1_N */ - pin_mask |= (1 << 23); /* CFRNW -> DIR */ - pin_mask |= (1 << 24); /* NWAIT <- IORDY */ - - select_peripheral(PIOE, pin_mask, PERIPH_A, 0); - - common_pins_initialized = true; - } - - select_peripheral(PIOB, extint_pin, PERIPH_A, AT32_GPIOF_DEGLITCH); - - pdev->resource[1].start = EIM_IRQ_BASE + extint; - pdev->resource[1].end = pdev->resource[1].start; - - return 0; -} - -struct platform_device *__init -at32_add_device_ide(unsigned int id, unsigned int extint, - struct ide_platform_data *data) -{ - struct platform_device *pdev; - - pdev = platform_device_alloc("at32_ide", id); - if (!pdev) - goto fail; - - if (platform_device_add_data(pdev, data, - sizeof(struct ide_platform_data))) - goto fail; - - if (at32_init_ide_or_cf(pdev, data->cs, extint)) - goto fail; - - platform_device_add(pdev); - return pdev; - -fail: - platform_device_put(pdev); - return NULL; -} - -struct platform_device *__init -at32_add_device_cf(unsigned int id, unsigned int extint, - struct cf_platform_data *data) -{ - struct platform_device *pdev; - - pdev = platform_device_alloc("at32_cf", id); - if (!pdev) - goto fail; - - if (platform_device_add_data(pdev, data, - sizeof(struct cf_platform_data))) - goto fail; - - if (at32_init_ide_or_cf(pdev, data->cs, extint)) - goto fail; - - if (gpio_is_valid(data->detect_pin)) - at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH); - if (gpio_is_valid(data->reset_pin)) - at32_select_gpio(data->reset_pin, 0); - if (gpio_is_valid(data->vcc_pin)) - at32_select_gpio(data->vcc_pin, 0); - /* READY is used as extint, so we can't select it as gpio */ - - platform_device_add(pdev); - return pdev; - -fail: - platform_device_put(pdev); - return NULL; -} -#endif - -/* -------------------------------------------------------------------- - * NAND Flash / SmartMedia - * -------------------------------------------------------------------- */ -static struct resource smc_cs3_resource[] __initdata = { - { - .start = 0x0c000000, - .end = 0x0fffffff, - .flags = IORESOURCE_MEM, - }, { - .start = 0xfff03c00, - .end = 0xfff03fff, - .flags = IORESOURCE_MEM, - }, -}; - -struct platform_device *__init -at32_add_device_nand(unsigned int id, struct atmel_nand_data *data) -{ - struct platform_device *pdev; - - if (id != 0 || !data) - return NULL; - - pdev = platform_device_alloc("atmel_nand", id); - if (!pdev) - goto fail; - - if (platform_device_add_resources(pdev, smc_cs3_resource, - ARRAY_SIZE(smc_cs3_resource))) - goto fail; - - /* For at32ap7000, we use the reset workaround for nand driver */ - data->need_reset_workaround = true; - - if (platform_device_add_data(pdev, data, - sizeof(struct atmel_nand_data))) - goto fail; - - hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_NAND_ENABLE); - if (data->enable_pin) - at32_select_gpio(data->enable_pin, - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - if (data->rdy_pin) - at32_select_gpio(data->rdy_pin, 0); - if (data->det_pin) - at32_select_gpio(data->det_pin, 0); - - platform_device_add(pdev); - return pdev; - -fail: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * AC97C - * -------------------------------------------------------------------- */ -static struct resource atmel_ac97c0_resource[] __initdata = { - PBMEM(0xfff02800), - IRQ(29), -}; -static struct clk atmel_ac97c0_pclk = { - .name = "pclk", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .index = 10, -}; - -struct platform_device *__init -at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, - unsigned int flags) -{ - struct platform_device *pdev; - struct dw_dma_slave *rx_dws; - struct dw_dma_slave *tx_dws; - struct ac97c_platform_data _data; - u32 pin_mask; - - if (id != 0) - return NULL; - - pdev = platform_device_alloc("atmel_ac97c", id); - if (!pdev) - return NULL; - - if (platform_device_add_resources(pdev, atmel_ac97c0_resource, - ARRAY_SIZE(atmel_ac97c0_resource))) - goto out_free_resources; - - if (!data) { - data = &_data; - memset(data, 0, sizeof(struct ac97c_platform_data)); - data->reset_pin = -ENODEV; - } - - rx_dws = &data->rx_dws; - tx_dws = &data->tx_dws; - - /* Check if DMA slave interface for capture should be configured. */ - if (flags & AC97C_CAPTURE) { - rx_dws->dma_dev = &dw_dmac0_device.dev; - rx_dws->src_id = 3; - rx_dws->m_master = 0; - rx_dws->p_master = 1; - } - - /* Check if DMA slave interface for playback should be configured. */ - if (flags & AC97C_PLAYBACK) { - tx_dws->dma_dev = &dw_dmac0_device.dev; - tx_dws->dst_id = 4; - tx_dws->m_master = 0; - tx_dws->p_master = 1; - } - - if (platform_device_add_data(pdev, data, - sizeof(struct ac97c_platform_data))) - goto out_free_resources; - - /* SDO | SYNC | SCLK | SDI */ - pin_mask = (1 << 20) | (1 << 21) | (1 << 22) | (1 << 23); - - select_peripheral(PIOB, pin_mask, PERIPH_B, 0); - - if (gpio_is_valid(data->reset_pin)) - at32_select_gpio(data->reset_pin, AT32_GPIOF_OUTPUT - | AT32_GPIOF_HIGH); - - atmel_ac97c0_pclk.dev = &pdev->dev; - - platform_device_add(pdev); - return pdev; - -out_free_resources: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * ABDAC - * -------------------------------------------------------------------- */ -static struct resource abdac0_resource[] __initdata = { - PBMEM(0xfff02000), - IRQ(27), -}; -static struct clk abdac0_pclk = { - .name = "pclk", - .parent = &pbb_clk, - .mode = pbb_clk_mode, - .get_rate = pbb_clk_get_rate, - .index = 8, -}; -static struct clk abdac0_sample_clk = { - .name = "sample_clk", - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 6, -}; - -struct platform_device *__init -at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data) -{ - struct platform_device *pdev; - struct dw_dma_slave *dws; - u32 pin_mask; - - if (id != 0 || !data) - return NULL; - - pdev = platform_device_alloc("atmel_abdac", id); - if (!pdev) - return NULL; - - if (platform_device_add_resources(pdev, abdac0_resource, - ARRAY_SIZE(abdac0_resource))) - goto out_free_resources; - - dws = &data->dws; - - dws->dma_dev = &dw_dmac0_device.dev; - dws->dst_id = 2; - dws->m_master = 0; - dws->p_master = 1; - - if (platform_device_add_data(pdev, data, - sizeof(struct atmel_abdac_pdata))) - goto out_free_resources; - - pin_mask = (1 << 20) | (1 << 22); /* DATA1 & DATAN1 */ - pin_mask |= (1 << 21) | (1 << 23); /* DATA0 & DATAN0 */ - - select_peripheral(PIOB, pin_mask, PERIPH_A, 0); - - abdac0_pclk.dev = &pdev->dev; - abdac0_sample_clk.dev = &pdev->dev; - - platform_device_add(pdev); - return pdev; - -out_free_resources: - platform_device_put(pdev); - return NULL; -} - -/* -------------------------------------------------------------------- - * GCLK - * -------------------------------------------------------------------- */ -static struct clk gclk0 = { - .name = "gclk0", - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 0, -}; -static struct clk gclk1 = { - .name = "gclk1", - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 1, -}; -static struct clk gclk2 = { - .name = "gclk2", - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 2, -}; -static struct clk gclk3 = { - .name = "gclk3", - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 3, -}; -static struct clk gclk4 = { - .name = "gclk4", - .mode = genclk_mode, - .get_rate = genclk_get_rate, - .set_rate = genclk_set_rate, - .set_parent = genclk_set_parent, - .index = 4, -}; - -static __initdata struct clk *init_clocks[] = { - &osc32k, - &osc0, - &osc1, - &pll0, - &pll1, - &cpu_clk, - &hsb_clk, - &pba_clk, - &pbb_clk, - &at32_pm_pclk, - &at32_intc0_pclk, - &at32_hmatrix_clk, - &ebi_clk, - &hramc_clk, - &sdramc_clk, - &smc0_pclk, - &smc0_mck, - &pdc_hclk, - &pdc_pclk, - &dw_dmac0_hclk, - &pico_clk, - &pio0_mck, - &pio1_mck, - &pio2_mck, - &pio3_mck, - &pio4_mck, - &at32_tcb0_t0_clk, - &at32_tcb1_t0_clk, - &atmel_psif0_pclk, - &atmel_psif1_pclk, - &atmel_usart0_usart, - &atmel_usart1_usart, - &atmel_usart2_usart, - &atmel_usart3_usart, - &atmel_pwm0_mck, -#if defined(CONFIG_CPU_AT32AP7000) - &macb0_hclk, - &macb0_pclk, - &macb1_hclk, - &macb1_pclk, -#endif - &atmel_spi0_spi_clk, - &atmel_spi1_spi_clk, - &atmel_twi0_pclk, - &atmel_mci0_pclk, -#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) - &atmel_lcdfb0_hclk, - &atmel_lcdfb0_pixclk, -#endif - &ssc0_pclk, - &ssc1_pclk, - &ssc2_pclk, - &usba0_hclk, - &usba0_pclk, - &atmel_ac97c0_pclk, - &abdac0_pclk, - &abdac0_sample_clk, - &gclk0, - &gclk1, - &gclk2, - &gclk3, - &gclk4, -}; - -void __init setup_platform(void) -{ - u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; - int i; - - if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) { - main_clock = &pll0; - cpu_clk.parent = &pll0; - } else { - main_clock = &osc0; - cpu_clk.parent = &osc0; - } - - if (pm_readl(PLL0) & PM_BIT(PLLOSC)) - pll0.parent = &osc1; - if (pm_readl(PLL1) & PM_BIT(PLLOSC)) - pll1.parent = &osc1; - - genclk_init_parent(&gclk0); - genclk_init_parent(&gclk1); - genclk_init_parent(&gclk2); - genclk_init_parent(&gclk3); - genclk_init_parent(&gclk4); -#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) - genclk_init_parent(&atmel_lcdfb0_pixclk); -#endif - genclk_init_parent(&abdac0_sample_clk); - - /* - * Build initial dynamic clock list by registering all clocks - * from the array. - * At the same time, turn on all clocks that have at least one - * user already, and turn off everything else. We only do this - * for module clocks, and even though it isn't particularly - * pretty to check the address of the mode function, it should - * do the trick... - */ - for (i = 0; i < ARRAY_SIZE(init_clocks); i++) { - struct clk *clk = init_clocks[i]; - - /* first, register clock */ - at32_clk_register(clk); - - if (clk->users == 0) - continue; - - if (clk->mode == &cpu_clk_mode) - cpu_mask |= 1 << clk->index; - else if (clk->mode == &hsb_clk_mode) - hsb_mask |= 1 << clk->index; - else if (clk->mode == &pba_clk_mode) - pba_mask |= 1 << clk->index; - else if (clk->mode == &pbb_clk_mode) - pbb_mask |= 1 << clk->index; - } - - pm_writel(CPU_MASK, cpu_mask); - pm_writel(HSB_MASK, hsb_mask); - pm_writel(PBA_MASK, pba_mask); - pm_writel(PBB_MASK, pbb_mask); - - /* Initialize the port muxes */ - at32_init_pio(&pio0_device); - at32_init_pio(&pio1_device); - at32_init_pio(&pio2_device); - at32_init_pio(&pio3_device); - at32_init_pio(&pio4_device); -} - -struct gen_pool *sram_pool; - -static int __init sram_init(void) -{ - struct gen_pool *pool; - - /* 1KiB granularity */ - pool = gen_pool_create(10, -1); - if (!pool) - goto fail; - - if (gen_pool_add(pool, 0x24000000, 0x8000, -1)) - goto err_pool_add; - - sram_pool = pool; - return 0; - -err_pool_add: - gen_pool_destroy(pool); -fail: - pr_err("Failed to create SRAM pool\n"); - return -ENOMEM; -} -core_initcall(sram_init); diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c deleted file mode 100644 index fdf1caecb7b9..000000000000 --- a/arch/avr32/mach-at32ap/clock.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Clock management for AT32AP CPUs - * - * Copyright (C) 2006 Atmel Corporation - * - * Based on arch/arm/mach-at91/clock.c - * Copyright (C) 2005 David Brownell - * Copyright (C) 2005 Ivan Kokshaysky - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/export.h> -#include <linux/device.h> -#include <linux/string.h> -#include <linux/list.h> - -#include <mach/chip.h> - -#include "clock.h" - -/* at32 clock list */ -static LIST_HEAD(at32_clock_list); - -static DEFINE_SPINLOCK(clk_lock); -static DEFINE_SPINLOCK(clk_list_lock); - -void at32_clk_register(struct clk *clk) -{ - spin_lock(&clk_list_lock); - /* add the new item to the end of the list */ - list_add_tail(&clk->list, &at32_clock_list); - spin_unlock(&clk_list_lock); -} - -static struct clk *__clk_get(struct device *dev, const char *id) -{ - struct clk *clk; - - list_for_each_entry(clk, &at32_clock_list, list) { - if (clk->dev == dev && strcmp(id, clk->name) == 0) { - return clk; - } - } - - return ERR_PTR(-ENOENT); -} - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *clk; - - spin_lock(&clk_list_lock); - clk = __clk_get(dev, id); - spin_unlock(&clk_list_lock); - - return clk; -} - -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - /* clocks are static for now, we can't free them */ -} -EXPORT_SYMBOL(clk_put); - -static void __clk_enable(struct clk *clk) -{ - if (clk->parent) - __clk_enable(clk->parent); - if (clk->users++ == 0 && clk->mode) - clk->mode(clk, 1); -} - -int clk_enable(struct clk *clk) -{ - unsigned long flags; - - if (!clk) - return 0; - - spin_lock_irqsave(&clk_lock, flags); - __clk_enable(clk); - spin_unlock_irqrestore(&clk_lock, flags); - - return 0; -} -EXPORT_SYMBOL(clk_enable); - -static void __clk_disable(struct clk *clk) -{ - if (clk->users == 0) { - printk(KERN_ERR "%s: mismatched disable\n", clk->name); - WARN_ON(1); - return; - } - - if (--clk->users == 0 && clk->mode) - clk->mode(clk, 0); - if (clk->parent) - __clk_disable(clk->parent); -} - -void clk_disable(struct clk *clk) -{ - unsigned long flags; - - if (IS_ERR_OR_NULL(clk)) - return; - - spin_lock_irqsave(&clk_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clk_lock, flags); -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - unsigned long flags; - unsigned long rate; - - if (!clk) - return 0; - - spin_lock_irqsave(&clk_lock, flags); - rate = clk->get_rate(clk); - spin_unlock_irqrestore(&clk_lock, flags); - - return rate; -} -EXPORT_SYMBOL(clk_get_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned long flags, actual_rate; - - if (!clk) - return 0; - - if (!clk->set_rate) - return -ENOSYS; - - spin_lock_irqsave(&clk_lock, flags); - actual_rate = clk->set_rate(clk, rate, 0); - spin_unlock_irqrestore(&clk_lock, flags); - - return actual_rate; -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - unsigned long flags; - long ret; - - if (!clk) - return 0; - - if (!clk->set_rate) - return -ENOSYS; - - spin_lock_irqsave(&clk_lock, flags); - ret = clk->set_rate(clk, rate, 1); - spin_unlock_irqrestore(&clk_lock, flags); - - return (ret < 0) ? ret : 0; -} -EXPORT_SYMBOL(clk_set_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - unsigned long flags; - int ret; - - if (!clk) - return 0; - - if (!clk->set_parent) - return -ENOSYS; - - spin_lock_irqsave(&clk_lock, flags); - ret = clk->set_parent(clk, parent); - spin_unlock_irqrestore(&clk_lock, flags); - - return ret; -} -EXPORT_SYMBOL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - return !clk ? NULL : clk->parent; -} -EXPORT_SYMBOL(clk_get_parent); - - - -#ifdef CONFIG_DEBUG_FS - -/* /sys/kernel/debug/at32ap_clk */ - -#include <linux/io.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include "pm.h" - - -#define NEST_DELTA 2 -#define NEST_MAX 6 - -struct clkinf { - struct seq_file *s; - unsigned nest; -}; - -static void -dump_clock(struct clk *parent, struct clkinf *r) -{ - unsigned nest = r->nest; - char buf[16 + NEST_MAX]; - struct clk *clk; - unsigned i; - - /* skip clocks coupled to devices that aren't registered */ - if (parent->dev && !dev_name(parent->dev) && !parent->users) - return; - - /* <nest spaces> name <pad to end> */ - memset(buf, ' ', sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; - i = strlen(parent->name); - memcpy(buf + nest, parent->name, - min(i, (unsigned)(sizeof(buf) - 1 - nest))); - - seq_printf(r->s, "%s%c users=%2d %-3s %9ld Hz", - buf, parent->set_parent ? '*' : ' ', - parent->users, - parent->users ? "on" : "off", /* NOTE: not-paranoid!! */ - clk_get_rate(parent)); - if (parent->dev) - seq_printf(r->s, ", for %s", dev_name(parent->dev)); - seq_putc(r->s, '\n'); - - /* cost of this scan is small, but not linear... */ - r->nest = nest + NEST_DELTA; - - list_for_each_entry(clk, &at32_clock_list, list) { - if (clk->parent == parent) - dump_clock(clk, r); - } - r->nest = nest; -} - -static int clk_show(struct seq_file *s, void *unused) -{ - struct clkinf r; - int i; - struct clk *clk; - - /* show all the power manager registers */ - seq_printf(s, - "MCCTRL = %8x\n" - "CKSEL = %8x\n" - "CPUMASK = %8x\n" - "HSBMASK = %8x\n" - "PBAMASK = %8x\n" - "PBBMASK = %8x\n" - "PLL0 = %8x\n" - "PLL1 = %8x\n" - "IMR = %8x\n", - pm_readl(MCCTRL), - pm_readl(CKSEL), - pm_readl(CPU_MASK), - pm_readl(HSB_MASK), - pm_readl(PBA_MASK), - pm_readl(PBB_MASK), - pm_readl(PLL0), - pm_readl(PLL1), - pm_readl(IMR)); - for (i = 0; i < 8; i++) { - if (i == 5) - continue; - seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i))); - } - - seq_putc(s, '\n'); - r.s = s; - r.nest = 0; - /* protected from changes on the list while dumping */ - spin_lock(&clk_list_lock); - - /* show clock tree as derived from the three oscillators */ - clk = __clk_get(NULL, "osc32k"); - dump_clock(clk, &r); - clk_put(clk); - - clk = __clk_get(NULL, "osc0"); - dump_clock(clk, &r); - clk_put(clk); - - clk = __clk_get(NULL, "osc1"); - dump_clock(clk, &r); - clk_put(clk); - - spin_unlock(&clk_list_lock); - - return 0; -} - -static int clk_open(struct inode *inode, struct file *file) -{ - return single_open(file, clk_show, NULL); -} - -static const struct file_operations clk_operations = { - .open = clk_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init clk_debugfs_init(void) -{ - (void) debugfs_create_file("at32ap_clk", S_IFREG | S_IRUGO, - NULL, NULL, &clk_operations); - - return 0; -} -postcore_initcall(clk_debugfs_init); - -#endif diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h deleted file mode 100644 index 4c7ebbdc6dfa..000000000000 --- a/arch/avr32/mach-at32ap/clock.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Clock management for AT32AP CPUs - * - * Copyright (C) 2006 Atmel Corporation - * - * Based on arch/arm/mach-at91/clock.c - * Copyright (C) 2005 David Brownell - * Copyright (C) 2005 Ivan Kokshaysky - * - * 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/clk.h> -#include <linux/list.h> - - -void at32_clk_register(struct clk *clk); - -struct clk { - struct list_head list; /* linking element */ - const char *name; /* Clock name/function */ - struct device *dev; /* Device the clock is used by */ - struct clk *parent; /* Parent clock, if any */ - void (*mode)(struct clk *clk, int enabled); - unsigned long (*get_rate)(struct clk *clk); - long (*set_rate)(struct clk *clk, unsigned long rate, - int apply); - int (*set_parent)(struct clk *clk, struct clk *parent); - u16 users; /* Enabled if non-zero */ - u16 index; /* Sibling index */ -}; - -unsigned long pba_clk_get_rate(struct clk *clk); -void pba_clk_mode(struct clk *clk, int enabled); diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c deleted file mode 100644 index 96cabad68489..000000000000 --- a/arch/avr32/mach-at32ap/extint.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * External interrupt handling for AT32AP CPUs - * - * Copyright (C) 2006 Atmel Corporation - * - * 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/errno.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/random.h> -#include <linux/slab.h> - -#include <asm/io.h> - -/* EIC register offsets */ -#define EIC_IER 0x0000 -#define EIC_IDR 0x0004 -#define EIC_IMR 0x0008 -#define EIC_ISR 0x000c -#define EIC_ICR 0x0010 -#define EIC_MODE 0x0014 -#define EIC_EDGE 0x0018 -#define EIC_LEVEL 0x001c -#define EIC_NMIC 0x0024 - -/* Bitfields in NMIC */ -#define EIC_NMIC_ENABLE (1 << 0) - -/* Bit manipulation macros */ -#define EIC_BIT(name) \ - (1 << EIC_##name##_OFFSET) -#define EIC_BF(name,value) \ - (((value) & ((1 << EIC_##name##_SIZE) - 1)) \ - << EIC_##name##_OFFSET) -#define EIC_BFEXT(name,value) \ - (((value) >> EIC_##name##_OFFSET) \ - & ((1 << EIC_##name##_SIZE) - 1)) -#define EIC_BFINS(name,value,old) \ - (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \ - << EIC_##name##_OFFSET)) \ - | EIC_BF(name,value)) - -/* Register access macros */ -#define eic_readl(port,reg) \ - __raw_readl((port)->regs + EIC_##reg) -#define eic_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + EIC_##reg) - -struct eic { - void __iomem *regs; - struct irq_chip *chip; - unsigned int first_irq; -}; - -static struct eic *nmi_eic; -static bool nmi_enabled; - -static void eic_ack_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq)); -} - -static void eic_mask_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq)); -} - -static void eic_mask_ack_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq)); - eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq)); -} - -static void eic_unmask_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, IER, 1 << (d->irq - eic->first_irq)); -} - -static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq; - unsigned int i = irq - eic->first_irq; - u32 mode, edge, level; - - flow_type &= IRQ_TYPE_SENSE_MASK; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - mode = eic_readl(eic, MODE); - edge = eic_readl(eic, EDGE); - level = eic_readl(eic, LEVEL); - - switch (flow_type) { - case IRQ_TYPE_LEVEL_LOW: - mode |= 1 << i; - level &= ~(1 << i); - break; - case IRQ_TYPE_LEVEL_HIGH: - mode |= 1 << i; - level |= 1 << i; - break; - case IRQ_TYPE_EDGE_RISING: - mode &= ~(1 << i); - edge |= 1 << i; - break; - case IRQ_TYPE_EDGE_FALLING: - mode &= ~(1 << i); - edge &= ~(1 << i); - break; - default: - return -EINVAL; - } - - eic_writel(eic, MODE, mode); - eic_writel(eic, EDGE, edge); - eic_writel(eic, LEVEL, level); - - irqd_set_trigger_type(d, flow_type); - if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - irq_set_handler_locked(d, handle_level_irq); - else - irq_set_handler_locked(d, handle_edge_irq); - - return IRQ_SET_MASK_OK_NOCOPY; -} - -static struct irq_chip eic_chip = { - .name = "eic", - .irq_ack = eic_ack_irq, - .irq_mask = eic_mask_irq, - .irq_mask_ack = eic_mask_ack_irq, - .irq_unmask = eic_unmask_irq, - .irq_set_type = eic_set_irq_type, -}; - -static void demux_eic_irq(struct irq_desc *desc) -{ - struct eic *eic = irq_desc_get_handler_data(desc); - unsigned long status, pending; - unsigned int i; - - status = eic_readl(eic, ISR); - pending = status & eic_readl(eic, IMR); - - while (pending) { - i = fls(pending) - 1; - pending &= ~(1 << i); - - generic_handle_irq(i + eic->first_irq); - } -} - -int nmi_enable(void) -{ - nmi_enabled = true; - - if (nmi_eic) - eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); - - return 0; -} - -void nmi_disable(void) -{ - if (nmi_eic) - eic_writel(nmi_eic, NMIC, 0); - - nmi_enabled = false; -} - -static int __init eic_probe(struct platform_device *pdev) -{ - struct eic *eic; - struct resource *regs; - unsigned int i; - unsigned int nr_of_irqs; - unsigned int int_irq; - int ret; - u32 pattern; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int_irq = platform_get_irq(pdev, 0); - if (!regs || (int)int_irq <= 0) { - dev_dbg(&pdev->dev, "missing regs and/or irq resource\n"); - return -ENXIO; - } - - ret = -ENOMEM; - eic = kzalloc(sizeof(struct eic), GFP_KERNEL); - if (!eic) { - dev_dbg(&pdev->dev, "no memory for eic structure\n"); - goto err_kzalloc; - } - - eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id; - eic->regs = ioremap(regs->start, resource_size(regs)); - if (!eic->regs) { - dev_dbg(&pdev->dev, "failed to map regs\n"); - goto err_ioremap; - } - - /* - * Find out how many interrupt lines that are actually - * implemented in hardware. - */ - eic_writel(eic, IDR, ~0UL); - eic_writel(eic, MODE, ~0UL); - pattern = eic_readl(eic, MODE); - nr_of_irqs = fls(pattern); - - /* Trigger on low level unless overridden by driver */ - eic_writel(eic, EDGE, 0UL); - eic_writel(eic, LEVEL, 0UL); - - eic->chip = &eic_chip; - - for (i = 0; i < nr_of_irqs; i++) { - irq_set_chip_and_handler(eic->first_irq + i, &eic_chip, - handle_level_irq); - irq_set_chip_data(eic->first_irq + i, eic); - } - - irq_set_chained_handler_and_data(int_irq, demux_eic_irq, eic); - - if (pdev->id == 0) { - nmi_eic = eic; - if (nmi_enabled) - /* - * Someone tried to enable NMI before we were - * ready. Do it now. - */ - nmi_enable(); - } - - dev_info(&pdev->dev, - "External Interrupt Controller at 0x%p, IRQ %u\n", - eic->regs, int_irq); - dev_info(&pdev->dev, - "Handling %u external IRQs, starting with IRQ %u\n", - nr_of_irqs, eic->first_irq); - - return 0; - -err_ioremap: - kfree(eic); -err_kzalloc: - return ret; -} - -static struct platform_driver eic_driver = { - .driver = { - .name = "at32_eic", - }, -}; - -static int __init eic_init(void) -{ - return platform_driver_probe(&eic_driver, eic_probe); -} -arch_initcall(eic_init); diff --git a/arch/avr32/mach-at32ap/hmatrix.c b/arch/avr32/mach-at32ap/hmatrix.c deleted file mode 100644 index 48f5ede77468..000000000000 --- a/arch/avr32/mach-at32ap/hmatrix.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * High-Speed Bus Matrix helper functions - * - * Copyright (C) 2008 Atmel Corporation - * - * 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/clk.h> -#include <linux/io.h> - -#include <mach/chip.h> -#include <mach/hmatrix.h> - -static inline void __hmatrix_write_reg(unsigned long offset, u32 value) -{ - __raw_writel(value, (void __iomem __force *)(HMATRIX_BASE + offset)); -} - -static inline u32 __hmatrix_read_reg(unsigned long offset) -{ - return __raw_readl((void __iomem __force *)(HMATRIX_BASE + offset)); -} - -/** - * hmatrix_write_reg - write HMATRIX configuration register - * @offset: register offset - * @value: value to be written to the register at @offset - */ -void hmatrix_write_reg(unsigned long offset, u32 value) -{ - clk_enable(&at32_hmatrix_clk); - __hmatrix_write_reg(offset, value); - __hmatrix_read_reg(offset); - clk_disable(&at32_hmatrix_clk); -} - -/** - * hmatrix_read_reg - read HMATRIX configuration register - * @offset: register offset - * - * Returns the value of the register at @offset. - */ -u32 hmatrix_read_reg(unsigned long offset) -{ - u32 value; - - clk_enable(&at32_hmatrix_clk); - value = __hmatrix_read_reg(offset); - clk_disable(&at32_hmatrix_clk); - - return value; -} - -/** - * hmatrix_sfr_set_bits - set bits in a slave's Special Function Register - * @slave_id: operate on the SFR belonging to this slave - * @mask: mask of bits to be set in the SFR - */ -void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask) -{ - u32 value; - - clk_enable(&at32_hmatrix_clk); - value = __hmatrix_read_reg(HMATRIX_SFR(slave_id)); - value |= mask; - __hmatrix_write_reg(HMATRIX_SFR(slave_id), value); - __hmatrix_read_reg(HMATRIX_SFR(slave_id)); - clk_disable(&at32_hmatrix_clk); -} - -/** - * hmatrix_sfr_set_bits - clear bits in a slave's Special Function Register - * @slave_id: operate on the SFR belonging to this slave - * @mask: mask of bits to be cleared in the SFR - */ -void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask) -{ - u32 value; - - clk_enable(&at32_hmatrix_clk); - value = __hmatrix_read_reg(HMATRIX_SFR(slave_id)); - value &= ~mask; - __hmatrix_write_reg(HMATRIX_SFR(slave_id), value); - __hmatrix_read_reg(HMATRIX_SFR(slave_id)); - clk_disable(&at32_hmatrix_clk); -} diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c deleted file mode 100644 index f66245e6e63e..000000000000 --- a/arch/avr32/mach-at32ap/hsmc.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Static Memory Controller for AT32 chips - * - * Copyright (C) 2006 Atmel Corporation - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> - -#include <asm/io.h> -#include <mach/smc.h> - -#include "hsmc.h" - -#define NR_CHIP_SELECTS 6 - -struct hsmc { - void __iomem *regs; - struct clk *pclk; - struct clk *mck; -}; - -static struct hsmc *hsmc; - -void smc_set_timing(struct smc_config *config, - const struct smc_timing *timing) -{ - int recover; - int cycle; - - unsigned long mul; - - /* Reset all SMC timings */ - config->ncs_read_setup = 0; - config->nrd_setup = 0; - config->ncs_write_setup = 0; - config->nwe_setup = 0; - config->ncs_read_pulse = 0; - config->nrd_pulse = 0; - config->ncs_write_pulse = 0; - config->nwe_pulse = 0; - config->read_cycle = 0; - config->write_cycle = 0; - - /* - * cycles = x / T = x * f - * = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536 - * = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536 - */ - mul = (clk_get_rate(hsmc->mck) / 10000) << 16; - mul /= 100000; - -#define ns2cyc(x) ((((x) * mul) + 65535) >> 16) - - if (timing->ncs_read_setup > 0) - config->ncs_read_setup = ns2cyc(timing->ncs_read_setup); - - if (timing->nrd_setup > 0) - config->nrd_setup = ns2cyc(timing->nrd_setup); - - if (timing->ncs_write_setup > 0) - config->ncs_write_setup = ns2cyc(timing->ncs_write_setup); - - if (timing->nwe_setup > 0) - config->nwe_setup = ns2cyc(timing->nwe_setup); - - if (timing->ncs_read_pulse > 0) - config->ncs_read_pulse = ns2cyc(timing->ncs_read_pulse); - - if (timing->nrd_pulse > 0) - config->nrd_pulse = ns2cyc(timing->nrd_pulse); - - if (timing->ncs_write_pulse > 0) - config->ncs_write_pulse = ns2cyc(timing->ncs_write_pulse); - - if (timing->nwe_pulse > 0) - config->nwe_pulse = ns2cyc(timing->nwe_pulse); - - if (timing->read_cycle > 0) - config->read_cycle = ns2cyc(timing->read_cycle); - - if (timing->write_cycle > 0) - config->write_cycle = ns2cyc(timing->write_cycle); - - /* Extend read cycle in needed */ - if (timing->ncs_read_recover > 0) - recover = ns2cyc(timing->ncs_read_recover); - else - recover = 1; - - cycle = config->ncs_read_setup + config->ncs_read_pulse + recover; - - if (config->read_cycle < cycle) - config->read_cycle = cycle; - - /* Extend read cycle in needed */ - if (timing->nrd_recover > 0) - recover = ns2cyc(timing->nrd_recover); - else - recover = 1; - - cycle = config->nrd_setup + config->nrd_pulse + recover; - - if (config->read_cycle < cycle) - config->read_cycle = cycle; - - /* Extend write cycle in needed */ - if (timing->ncs_write_recover > 0) - recover = ns2cyc(timing->ncs_write_recover); - else - recover = 1; - - cycle = config->ncs_write_setup + config->ncs_write_pulse + recover; - - if (config->write_cycle < cycle) - config->write_cycle = cycle; - - /* Extend write cycle in needed */ - if (timing->nwe_recover > 0) - recover = ns2cyc(timing->nwe_recover); - else - recover = 1; - - cycle = config->nwe_setup + config->nwe_pulse + recover; - - if (config->write_cycle < cycle) - config->write_cycle = cycle; -} -EXPORT_SYMBOL(smc_set_timing); - -int smc_set_configuration(int cs, const struct smc_config *config) -{ - unsigned long offset; - u32 setup, pulse, cycle, mode; - - if (!hsmc) - return -ENODEV; - if (cs >= NR_CHIP_SELECTS) - return -EINVAL; - - setup = (HSMC_BF(NWE_SETUP, config->nwe_setup) - | HSMC_BF(NCS_WR_SETUP, config->ncs_write_setup) - | HSMC_BF(NRD_SETUP, config->nrd_setup) - | HSMC_BF(NCS_RD_SETUP, config->ncs_read_setup)); - pulse = (HSMC_BF(NWE_PULSE, config->nwe_pulse) - | HSMC_BF(NCS_WR_PULSE, config->ncs_write_pulse) - | HSMC_BF(NRD_PULSE, config->nrd_pulse) - | HSMC_BF(NCS_RD_PULSE, config->ncs_read_pulse)); - cycle = (HSMC_BF(NWE_CYCLE, config->write_cycle) - | HSMC_BF(NRD_CYCLE, config->read_cycle)); - - switch (config->bus_width) { - case 1: - mode = HSMC_BF(DBW, HSMC_DBW_8_BITS); - break; - case 2: - mode = HSMC_BF(DBW, HSMC_DBW_16_BITS); - break; - case 4: - mode = HSMC_BF(DBW, HSMC_DBW_32_BITS); - break; - default: - return -EINVAL; - } - - switch (config->nwait_mode) { - case 0: - mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED); - break; - case 1: - mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED); - break; - case 2: - mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN); - break; - case 3: - mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY); - break; - default: - return -EINVAL; - } - - if (config->tdf_cycles) { - mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles); - } - - if (config->nrd_controlled) - mode |= HSMC_BIT(READ_MODE); - if (config->nwe_controlled) - mode |= HSMC_BIT(WRITE_MODE); - if (config->byte_write) - mode |= HSMC_BIT(BAT); - if (config->tdf_mode) - mode |= HSMC_BIT(TDF_MODE); - - pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", - cs, setup, pulse, cycle, mode); - - offset = cs * 0x10; - hsmc_writel(hsmc, SETUP0 + offset, setup); - hsmc_writel(hsmc, PULSE0 + offset, pulse); - hsmc_writel(hsmc, CYCLE0 + offset, cycle); - hsmc_writel(hsmc, MODE0 + offset, mode); - hsmc_readl(hsmc, MODE0); /* I/O barrier */ - - return 0; -} -EXPORT_SYMBOL(smc_set_configuration); - -static int hsmc_probe(struct platform_device *pdev) -{ - struct resource *regs; - struct clk *pclk, *mck; - int ret; - - if (hsmc) - return -EBUSY; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) - return -ENXIO; - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) - return PTR_ERR(pclk); - mck = clk_get(&pdev->dev, "mck"); - if (IS_ERR(mck)) { - ret = PTR_ERR(mck); - goto out_put_pclk; - } - - ret = -ENOMEM; - hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL); - if (!hsmc) - goto out_put_clocks; - - clk_enable(pclk); - clk_enable(mck); - - hsmc->pclk = pclk; - hsmc->mck = mck; - hsmc->regs = ioremap(regs->start, resource_size(regs)); - if (!hsmc->regs) - goto out_disable_clocks; - - dev_info(&pdev->dev, "Atmel Static Memory Controller at 0x%08lx\n", - (unsigned long)regs->start); - - platform_set_drvdata(pdev, hsmc); - - return 0; - -out_disable_clocks: - clk_disable(mck); - clk_disable(pclk); - kfree(hsmc); -out_put_clocks: - clk_put(mck); -out_put_pclk: - clk_put(pclk); - hsmc = NULL; - return ret; -} - -static struct platform_driver hsmc_driver = { - .probe = hsmc_probe, - .driver = { - .name = "smc", - }, -}; - -static int __init hsmc_init(void) -{ - return platform_driver_register(&hsmc_driver); -} -core_initcall(hsmc_init); diff --git a/arch/avr32/mach-at32ap/hsmc.h b/arch/avr32/mach-at32ap/hsmc.h deleted file mode 100644 index d1d48e26e393..000000000000 --- a/arch/avr32/mach-at32ap/hsmc.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Register definitions for Atmel Static Memory Controller (SMC) - * - * Copyright (C) 2006 Atmel Corporation - * - * 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 __ASM_AVR32_HSMC_H__ -#define __ASM_AVR32_HSMC_H__ - -/* HSMC register offsets */ -#define HSMC_SETUP0 0x0000 -#define HSMC_PULSE0 0x0004 -#define HSMC_CYCLE0 0x0008 -#define HSMC_MODE0 0x000c -#define HSMC_SETUP1 0x0010 -#define HSMC_PULSE1 0x0014 -#define HSMC_CYCLE1 0x0018 -#define HSMC_MODE1 0x001c -#define HSMC_SETUP2 0x0020 -#define HSMC_PULSE2 0x0024 -#define HSMC_CYCLE2 0x0028 -#define HSMC_MODE2 0x002c -#define HSMC_SETUP3 0x0030 -#define HSMC_PULSE3 0x0034 -#define HSMC_CYCLE3 0x0038 -#define HSMC_MODE3 0x003c -#define HSMC_SETUP4 0x0040 -#define HSMC_PULSE4 0x0044 -#define HSMC_CYCLE4 0x0048 -#define HSMC_MODE4 0x004c -#define HSMC_SETUP5 0x0050 -#define HSMC_PULSE5 0x0054 -#define HSMC_CYCLE5 0x0058 -#define HSMC_MODE5 0x005c - -/* Bitfields in SETUP0 */ -#define HSMC_NWE_SETUP_OFFSET 0 -#define HSMC_NWE_SETUP_SIZE 6 -#define HSMC_NCS_WR_SETUP_OFFSET 8 -#define HSMC_NCS_WR_SETUP_SIZE 6 -#define HSMC_NRD_SETUP_OFFSET 16 -#define HSMC_NRD_SETUP_SIZE 6 -#define HSMC_NCS_RD_SETUP_OFFSET 24 -#define HSMC_NCS_RD_SETUP_SIZE 6 - -/* Bitfields in PULSE0 */ -#define HSMC_NWE_PULSE_OFFSET 0 -#define HSMC_NWE_PULSE_SIZE 7 -#define HSMC_NCS_WR_PULSE_OFFSET 8 -#define HSMC_NCS_WR_PULSE_SIZE 7 -#define HSMC_NRD_PULSE_OFFSET 16 -#define HSMC_NRD_PULSE_SIZE 7 -#define HSMC_NCS_RD_PULSE_OFFSET 24 -#define HSMC_NCS_RD_PULSE_SIZE 7 - -/* Bitfields in CYCLE0 */ -#define HSMC_NWE_CYCLE_OFFSET 0 -#define HSMC_NWE_CYCLE_SIZE 9 -#define HSMC_NRD_CYCLE_OFFSET 16 -#define HSMC_NRD_CYCLE_SIZE 9 - -/* Bitfields in MODE0 */ -#define HSMC_READ_MODE_OFFSET 0 -#define HSMC_READ_MODE_SIZE 1 -#define HSMC_WRITE_MODE_OFFSET 1 -#define HSMC_WRITE_MODE_SIZE 1 -#define HSMC_EXNW_MODE_OFFSET 4 -#define HSMC_EXNW_MODE_SIZE 2 -#define HSMC_BAT_OFFSET 8 -#define HSMC_BAT_SIZE 1 -#define HSMC_DBW_OFFSET 12 -#define HSMC_DBW_SIZE 2 -#define HSMC_TDF_CYCLES_OFFSET 16 -#define HSMC_TDF_CYCLES_SIZE 4 -#define HSMC_TDF_MODE_OFFSET 20 -#define HSMC_TDF_MODE_SIZE 1 -#define HSMC_PMEN_OFFSET 24 -#define HSMC_PMEN_SIZE 1 -#define HSMC_PS_OFFSET 28 -#define HSMC_PS_SIZE 2 - -/* Constants for READ_MODE */ -#define HSMC_READ_MODE_NCS_CONTROLLED 0 -#define HSMC_READ_MODE_NRD_CONTROLLED 1 - -/* Constants for WRITE_MODE */ -#define HSMC_WRITE_MODE_NCS_CONTROLLED 0 -#define HSMC_WRITE_MODE_NWE_CONTROLLED 1 - -/* Constants for EXNW_MODE */ -#define HSMC_EXNW_MODE_DISABLED 0 -#define HSMC_EXNW_MODE_RESERVED 1 -#define HSMC_EXNW_MODE_FROZEN 2 -#define HSMC_EXNW_MODE_READY 3 - -/* Constants for BAT */ -#define HSMC_BAT_BYTE_SELECT 0 -#define HSMC_BAT_BYTE_WRITE 1 - -/* Constants for DBW */ -#define HSMC_DBW_8_BITS 0 -#define HSMC_DBW_16_BITS 1 -#define HSMC_DBW_32_BITS 2 - -/* Bit manipulation macros */ -#define HSMC_BIT(name) \ - (1 << HSMC_##name##_OFFSET) -#define HSMC_BF(name,value) \ - (((value) & ((1 << HSMC_##name##_SIZE) - 1)) \ - << HSMC_##name##_OFFSET) -#define HSMC_BFEXT(name,value) \ - (((value) >> HSMC_##name##_OFFSET) \ - & ((1 << HSMC_##name##_SIZE) - 1)) -#define HSMC_BFINS(name,value,old) \ - (((old) & ~(((1 << HSMC_##name##_SIZE) - 1) \ - << HSMC_##name##_OFFSET)) | HSMC_BF(name,value)) - -/* Register access macros */ -#define hsmc_readl(port,reg) \ - __raw_readl((port)->regs + HSMC_##reg) -#define hsmc_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + HSMC_##reg) - -#endif /* __ASM_AVR32_HSMC_H__ */ diff --git a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h deleted file mode 100644 index b9222bf895bc..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Pin definitions for AT32AP7000. - * - * Copyright (C) 2006 Atmel Corporation - * - * 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 __ASM_ARCH_AT32AP700X_H__ -#define __ASM_ARCH_AT32AP700X_H__ - -#define GPIO_PERIPH_A 0 -#define GPIO_PERIPH_B 1 - -/* - * Pin numbers identifying specific GPIO pins on the chip. They can - * also be converted to IRQ numbers by passing them through - * gpio_to_irq(). - */ -#define GPIO_PIOA_BASE (0) -#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32) -#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32) -#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32) -#define GPIO_PIOE_BASE (GPIO_PIOD_BASE + 32) - -#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N)) -#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N)) -#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N)) -#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N)) -#define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N)) - - -/* - * DMAC peripheral hardware handshaking interfaces, used with dw_dmac - */ -#define DMAC_MCI_RX 0 -#define DMAC_MCI_TX 1 -#define DMAC_DAC_TX 2 -#define DMAC_AC97_A_RX 3 -#define DMAC_AC97_A_TX 4 -#define DMAC_AC97_B_RX 5 -#define DMAC_AC97_B_TX 6 -#define DMAC_DMAREQ_0 7 -#define DMAC_DMAREQ_1 8 -#define DMAC_DMAREQ_2 9 -#define DMAC_DMAREQ_3 10 - -/* HSB master IDs */ -#define HMATRIX_MASTER_CPU_DCACHE 0 -#define HMATRIX_MASTER_CPU_ICACHE 1 -#define HMATRIX_MASTER_PDC 2 -#define HMATRIX_MASTER_ISI 3 -#define HMATRIX_MASTER_USBA 4 -#define HMATRIX_MASTER_LCDC 5 -#define HMATRIX_MASTER_MACB0 6 -#define HMATRIX_MASTER_MACB1 7 -#define HMATRIX_MASTER_DMACA_M0 8 -#define HMATRIX_MASTER_DMACA_M1 9 - -/* HSB slave IDs */ -#define HMATRIX_SLAVE_SRAM0 0 -#define HMATRIX_SLAVE_SRAM1 1 -#define HMATRIX_SLAVE_PBA 2 -#define HMATRIX_SLAVE_PBB 3 -#define HMATRIX_SLAVE_EBI 4 -#define HMATRIX_SLAVE_USBA 5 -#define HMATRIX_SLAVE_LCDC 6 -#define HMATRIX_SLAVE_DMACA 7 - -/* Bits in HMATRIX SFR4 (EBI) */ -#define HMATRIX_EBI_SDRAM_ENABLE (1 << 1) -#define HMATRIX_EBI_NAND_ENABLE (1 << 3) -#define HMATRIX_EBI_CF0_ENABLE (1 << 4) -#define HMATRIX_EBI_CF1_ENABLE (1 << 5) -#define HMATRIX_EBI_PULLUP_DISABLE (1 << 8) - -/* - * Base addresses of controllers that may be accessed early by - * platform code. - */ -#define PM_BASE 0xfff00000 -#define HMATRIX_BASE 0xfff00800 -#define SDRAMC_BASE 0xfff03800 - -/* LCDC on port C */ -#define ATMEL_LCDC_PC_CC (1ULL << 19) -#define ATMEL_LCDC_PC_HSYNC (1ULL << 20) -#define ATMEL_LCDC_PC_PCLK (1ULL << 21) -#define ATMEL_LCDC_PC_VSYNC (1ULL << 22) -#define ATMEL_LCDC_PC_DVAL (1ULL << 23) -#define ATMEL_LCDC_PC_MODE (1ULL << 24) -#define ATMEL_LCDC_PC_PWR (1ULL << 25) -#define ATMEL_LCDC_PC_DATA0 (1ULL << 26) -#define ATMEL_LCDC_PC_DATA1 (1ULL << 27) -#define ATMEL_LCDC_PC_DATA2 (1ULL << 28) -#define ATMEL_LCDC_PC_DATA3 (1ULL << 29) -#define ATMEL_LCDC_PC_DATA4 (1ULL << 30) -#define ATMEL_LCDC_PC_DATA5 (1ULL << 31) - -/* LCDC on port D */ -#define ATMEL_LCDC_PD_DATA6 (1ULL << 0) -#define ATMEL_LCDC_PD_DATA7 (1ULL << 1) -#define ATMEL_LCDC_PD_DATA8 (1ULL << 2) -#define ATMEL_LCDC_PD_DATA9 (1ULL << 3) -#define ATMEL_LCDC_PD_DATA10 (1ULL << 4) -#define ATMEL_LCDC_PD_DATA11 (1ULL << 5) -#define ATMEL_LCDC_PD_DATA12 (1ULL << 6) -#define ATMEL_LCDC_PD_DATA13 (1ULL << 7) -#define ATMEL_LCDC_PD_DATA14 (1ULL << 8) -#define ATMEL_LCDC_PD_DATA15 (1ULL << 9) -#define ATMEL_LCDC_PD_DATA16 (1ULL << 10) -#define ATMEL_LCDC_PD_DATA17 (1ULL << 11) -#define ATMEL_LCDC_PD_DATA18 (1ULL << 12) -#define ATMEL_LCDC_PD_DATA19 (1ULL << 13) -#define ATMEL_LCDC_PD_DATA20 (1ULL << 14) -#define ATMEL_LCDC_PD_DATA21 (1ULL << 15) -#define ATMEL_LCDC_PD_DATA22 (1ULL << 16) -#define ATMEL_LCDC_PD_DATA23 (1ULL << 17) - -/* LCDC on port E */ -#define ATMEL_LCDC_PE_CC (1ULL << (32 + 0)) -#define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1)) -#define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2)) -#define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3)) -#define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4)) -#define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5)) -#define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6)) -#define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7)) -#define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8)) -#define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9)) -#define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10)) -#define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11)) -#define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12)) -#define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13)) -#define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14)) -#define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15)) -#define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16)) -#define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17)) -#define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18)) - - -#define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN) - - -#define ATMEL_LCDC_PRI_24B_DATA ( \ - ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ - ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ - ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ - ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ - ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ - ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ - ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \ - ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ - ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \ - ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \ - ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \ - ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) - -#define ATMEL_LCDC_ALT_24B_DATA ( \ - ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ - ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ - ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ - ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ - ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ - ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ - ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \ - ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ - ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \ - ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \ - ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \ - ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) - -#define ATMEL_LCDC_PRI_18B_DATA ( \ - ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ - ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ - ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ - ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ - ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \ - ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ - ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \ - ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \ - ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) - -#define ATMEL_LCDC_ALT_18B_DATA ( \ - ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ - ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ - ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ - ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ - ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \ - ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ - ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \ - ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \ - ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) - -#define ATMEL_LCDC_PRI_15B_DATA ( \ - ATMEL_LCDC(PC, DATA3) | ATMEL_LCDC(PC, DATA4) | \ - ATMEL_LCDC(PC, DATA5) | ATMEL_LCDC(PD, DATA6) | \ - ATMEL_LCDC(PD, DATA7) | \ - ATMEL_LCDC(PD, DATA11) | ATMEL_LCDC(PD, DATA12) | \ - ATMEL_LCDC(PD, DATA13) | ATMEL_LCDC(PD, DATA14) | \ - ATMEL_LCDC(PD, DATA15) | \ - ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20) | \ - ATMEL_LCDC(PD, DATA21) | ATMEL_LCDC(PD, DATA22) | \ - ATMEL_LCDC(PD, DATA23)) - -#define ATMEL_LCDC_ALT_15B_DATA ( \ - ATMEL_LCDC(PE, DATA3) | ATMEL_LCDC(PE, DATA4) | \ - ATMEL_LCDC(PC, DATA5) | ATMEL_LCDC(PD, DATA6) | \ - ATMEL_LCDC(PD, DATA7) | \ - ATMEL_LCDC(PE, DATA11) | ATMEL_LCDC(PE, DATA12) | \ - ATMEL_LCDC(PD, DATA13) | ATMEL_LCDC(PD, DATA14) | \ - ATMEL_LCDC(PD, DATA15) | \ - ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20) | \ - ATMEL_LCDC(PE, DATA21) | ATMEL_LCDC(PD, DATA22) | \ - ATMEL_LCDC(PD, DATA23)) - -#define ATMEL_LCDC_PRI_CONTROL ( \ - ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \ - ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR)) - -#define ATMEL_LCDC_ALT_CONTROL ( \ - ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \ - ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR)) - -#define ATMEL_LCDC_CONTROL ( \ - ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \ - ATMEL_LCDC(PC, PCLK)) - -#define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA) - -#define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA) - -#define ATMEL_LCDC_PRI_18BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_18B_DATA) - -#define ATMEL_LCDC_ALT_18BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_18B_DATA) - -#define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA) - -#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA) - -/* Bitmask for all EBI data (D16..D31) pins on port E */ -#define ATMEL_EBI_PE_DATA_ALL (0x0000FFFF) - -#endif /* __ASM_ARCH_AT32AP700X_H__ */ diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h deleted file mode 100644 index f1a316d52c73..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Platform data definitions. - */ -#ifndef __ASM_ARCH_BOARD_H -#define __ASM_ARCH_BOARD_H - -#include <linux/types.h> -#include <linux/serial.h> -#include <linux/platform_data/macb.h> -#include <linux/platform_data/atmel.h> - -#define GPIO_PIN_NONE (-1) - -/* - * Clock rates for various on-board oscillators. The number of entries - * in this array is chip-dependent. - */ -extern unsigned long at32_board_osc_rates[]; - -/* - * This used to add essential system devices, but this is now done - * automatically. Please don't use it in new board code. - */ -static inline void __deprecated at32_add_system_devices(void) -{ - -} - -extern struct platform_device *atmel_default_console_device; - -/* Flags for selecting USART extra pins */ -#define ATMEL_USART_RTS 0x01 -#define ATMEL_USART_CTS 0x02 -#define ATMEL_USART_CLK 0x04 - -void at32_map_usart(unsigned int hw_id, unsigned int line, int flags); -struct platform_device *at32_add_device_usart(unsigned int id); - -struct platform_device * -at32_add_device_eth(unsigned int id, struct macb_platform_data *data); - -struct spi_board_info; -struct platform_device * -at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); -void at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n); - -struct atmel_lcdfb_pdata; -struct platform_device * -at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data, - unsigned long fbmem_start, unsigned long fbmem_len, - u64 pin_mask); - -struct usba_platform_data; -struct platform_device * -at32_add_device_usba(unsigned int id, struct usba_platform_data *data); - -struct ide_platform_data { - u8 cs; -}; -struct platform_device * -at32_add_device_ide(unsigned int id, unsigned int extint, - struct ide_platform_data *data); - -/* mask says which PWM channels to mux */ -struct platform_device *at32_add_device_pwm(u32 mask); - -/* depending on what's hooked up, not all SSC pins will be used */ -#define ATMEL_SSC_TK 0x01 -#define ATMEL_SSC_TF 0x02 -#define ATMEL_SSC_TD 0x04 -#define ATMEL_SSC_TX (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD) - -#define ATMEL_SSC_RK 0x10 -#define ATMEL_SSC_RF 0x20 -#define ATMEL_SSC_RD 0x40 -#define ATMEL_SSC_RX (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD) - -struct platform_device * -at32_add_device_ssc(unsigned int id, unsigned int flags); - -struct i2c_board_info; -struct platform_device *at32_add_device_twi(unsigned int id, - struct i2c_board_info *b, - unsigned int n); - -struct mci_platform_data; -struct platform_device * -at32_add_device_mci(unsigned int id, struct mci_platform_data *data); - -struct ac97c_platform_data; -struct platform_device * -at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, - unsigned int flags); - -struct atmel_abdac_pdata; -struct platform_device * -at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data); - -struct platform_device *at32_add_device_psif(unsigned int id); - -struct cf_platform_data { - int detect_pin; - int reset_pin; - int vcc_pin; - int ready_pin; - u8 cs; -}; -struct platform_device * -at32_add_device_cf(unsigned int id, unsigned int extint, - struct cf_platform_data *data); - -struct platform_device * -at32_add_device_nand(unsigned int id, struct atmel_nand_data *data); - -#endif /* __ASM_ARCH_BOARD_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/chip.h b/arch/avr32/mach-at32ap/include/mach/chip.h deleted file mode 100644 index 5efca6da6acb..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/chip.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * AVR32 chip-specific definitions - * - * Copyright (C) 2008 Atmel Corporation - * - * 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 __ASM_AVR32_ARCH_CHIP_H__ -#define __ASM_AVR32_ARCH_CHIP_H__ - -#if defined(CONFIG_CPU_AT32AP700X) -# include <mach/at32ap700x.h> -#else -# error Unknown chip type selected -#endif - -#endif /* __ASM_AVR32_ARCH_CHIP_H__ */ diff --git a/arch/avr32/mach-at32ap/include/mach/cpu.h b/arch/avr32/mach-at32ap/include/mach/cpu.h deleted file mode 100644 index 4181086f4ddc..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/cpu.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * AVR32 CPU identification - * - * Copyright (C) 2007 Atmel Corporation - * - * 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 __ASM_ARCH_CPU_H -#define __ASM_ARCH_CPU_H - -/* - * Only AT32AP7000 is defined for now. We can identify the specific - * chip at runtime, but I'm not sure if it's really worth it. - */ -#ifdef CONFIG_CPU_AT32AP700X -# define cpu_is_at32ap7000() (1) -#else -# define cpu_is_at32ap7000() (0) -#endif - -#endif /* __ASM_ARCH_CPU_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/gpio.h b/arch/avr32/mach-at32ap/include/mach/gpio.h deleted file mode 100644 index 0180f584ef03..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/gpio.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __ASM_AVR32_ARCH_GPIO_H -#define __ASM_AVR32_ARCH_GPIO_H - -#include <linux/compiler.h> -#include <asm/irq.h> - - -/* Some GPIO chips can manage IRQs; some can't. The exact numbers can - * be changed if needed, but for the moment they're not configurable. - */ -#define ARCH_NR_GPIOS (NR_GPIO_IRQS + 2 * 32) - - -/* Arch-neutral GPIO API, supporting both "native" and external GPIOs. */ -#include <asm-generic/gpio.h> - -static inline int gpio_get_value(unsigned int gpio) -{ - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned int gpio, int value) -{ - __gpio_set_value(gpio, value); -} - -static inline int gpio_cansleep(unsigned int gpio) -{ - return __gpio_cansleep(gpio); -} - - -static inline int gpio_to_irq(unsigned int gpio) -{ - if (gpio < NR_GPIO_IRQS) - return gpio + GPIO_IRQ_BASE; - return -EINVAL; -} - -static inline int irq_to_gpio(unsigned int irq) -{ - return irq - GPIO_IRQ_BASE; -} - -#endif /* __ASM_AVR32_ARCH_GPIO_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/hmatrix.h b/arch/avr32/mach-at32ap/include/mach/hmatrix.h deleted file mode 100644 index 7a368f227ebc..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/hmatrix.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * High-Speed Bus Matrix configuration registers - * - * Copyright (C) 2008 Atmel Corporation - * - * 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 __HMATRIX_H -#define __HMATRIX_H - -extern struct clk at32_hmatrix_clk; - -void hmatrix_write_reg(unsigned long offset, u32 value); -u32 hmatrix_read_reg(unsigned long offset); - -void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask); -void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask); - -/* Master Configuration register */ -#define HMATRIX_MCFG(m) (0x0000 + 4 * (m)) -/* Undefined length burst limit */ -# define HMATRIX_MCFG_ULBT_INFINITE 0 /* Infinite length */ -# define HMATRIX_MCFG_ULBT_SINGLE 1 /* Single Access */ -# define HMATRIX_MCFG_ULBT_FOUR_BEAT 2 /* Four beat */ -# define HMATRIX_MCFG_ULBT_EIGHT_BEAT 3 /* Eight beat */ -# define HMATRIX_MCFG_ULBT_SIXTEEN_BEAT 4 /* Sixteen beat */ - -/* Slave Configuration register */ -#define HMATRIX_SCFG(s) (0x0040 + 4 * (s)) -# define HMATRIX_SCFG_SLOT_CYCLE(x) ((x) << 0) /* Max burst cycles */ -# define HMATRIX_SCFG_DEFMSTR_NONE ( 0 << 16) /* No default master */ -# define HMATRIX_SCFG_DEFMSTR_LAST ( 1 << 16) /* Last def master */ -# define HMATRIX_SCFG_DEFMSTR_FIXED ( 2 << 16) /* Fixed def master */ -# define HMATRIX_SCFG_FIXED_DEFMSTR(m) ((m) << 18) /* Fixed master ID */ -# define HMATRIX_SCFG_ARBT_ROUND_ROBIN ( 0 << 24) /* RR arbitration */ -# define HMATRIX_SCFG_ARBT_FIXED_PRIO ( 1 << 24) /* Fixed priority */ - -/* Slave Priority register A (master 0..7) */ -#define HMATRIX_PRAS(s) (0x0080 + 8 * (s)) -# define HMATRIX_PRAS_PRIO(m, p) ((p) << ((m) * 4)) - -/* Slave Priority register A (master 8..15) */ -#define HMATRIX_PRBS(s) (0x0084 + 8 * (s)) -# define HMATRIX_PRBS_PRIO(m, p) ((p) << (((m) - 8) * 4)) - -/* Master Remap Control Register */ -#define HMATRIX_MRCR 0x0100 -# define HMATRIX_MRCR_REMAP(m) ( 1 << (m)) /* Remap master m */ - -/* Special Function Register. Bit definitions are chip-specific */ -#define HMATRIX_SFR(s) (0x0110 + 4 * (s)) - -#endif /* __HMATRIX_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/init.h b/arch/avr32/mach-at32ap/include/mach/init.h deleted file mode 100644 index bc40e3d46150..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/init.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * AT32AP platform initialization calls. - * - * Copyright (C) 2006 Atmel Corporation - * - * 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 __ASM_AVR32_AT32AP_INIT_H__ -#define __ASM_AVR32_AT32AP_INIT_H__ - -void setup_platform(void); -void setup_board(void); - -void at32_setup_serial_console(unsigned int usart_id); - -#endif /* __ASM_AVR32_AT32AP_INIT_H__ */ diff --git a/arch/avr32/mach-at32ap/include/mach/io.h b/arch/avr32/mach-at32ap/include/mach/io.h deleted file mode 100644 index 22ea79b74052..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/io.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __ASM_AVR32_ARCH_AT32AP_IO_H -#define __ASM_AVR32_ARCH_AT32AP_IO_H - -#include <linux/swab.h> - -#if defined(CONFIG_AP700X_32_BIT_SMC) -# define __swizzle_addr_b(addr) (addr ^ 3UL) -# define __swizzle_addr_w(addr) (addr ^ 2UL) -# define __swizzle_addr_l(addr) (addr) -# define ioswabb(a, x) (x) -# define ioswabw(a, x) (x) -# define ioswabl(a, x) (x) -# define __mem_ioswabb(a, x) (x) -# define __mem_ioswabw(a, x) swab16(x) -# define __mem_ioswabl(a, x) swab32(x) -#elif defined(CONFIG_AP700X_16_BIT_SMC) -# define __swizzle_addr_b(addr) (addr ^ 1UL) -# define __swizzle_addr_w(addr) (addr) -# define __swizzle_addr_l(addr) (addr) -# define ioswabb(a, x) (x) -# define ioswabw(a, x) (x) -# define ioswabl(a, x) swahw32(x) -# define __mem_ioswabb(a, x) (x) -# define __mem_ioswabw(a, x) swab16(x) -# define __mem_ioswabl(a, x) swahb32(x) -#else -# define __swizzle_addr_b(addr) (addr) -# define __swizzle_addr_w(addr) (addr) -# define __swizzle_addr_l(addr) (addr) -# define ioswabb(a, x) (x) -# define ioswabw(a, x) swab16(x) -# define ioswabl(a, x) swab32(x) -# define __mem_ioswabb(a, x) (x) -# define __mem_ioswabw(a, x) (x) -# define __mem_ioswabl(a, x) (x) -#endif - -#endif /* __ASM_AVR32_ARCH_AT32AP_IO_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/irq.h b/arch/avr32/mach-at32ap/include/mach/irq.h deleted file mode 100644 index 608e350368c7..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/irq.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __ASM_AVR32_ARCH_IRQ_H -#define __ASM_AVR32_ARCH_IRQ_H - -#define EIM_IRQ_BASE NR_INTERNAL_IRQS -#define NR_EIM_IRQS 32 -#define AT32_EXTINT(n) (EIM_IRQ_BASE + (n)) - -#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS) -#define NR_GPIO_CTLR (5 /*internal*/ + 1 /*external*/) -#define NR_GPIO_IRQS (NR_GPIO_CTLR * 32) - -#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS) - -#endif /* __ASM_AVR32_ARCH_IRQ_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/pm.h b/arch/avr32/mach-at32ap/include/mach/pm.h deleted file mode 100644 index f29ff2cd23d3..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/pm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * AVR32 AP Power Management. - * - * Copyright (C) 2008 Atmel Corporation - * - * 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 __ASM_AVR32_ARCH_PM_H -#define __ASM_AVR32_ARCH_PM_H - -/* Possible arguments to the "sleep" instruction */ -#define CPU_SLEEP_IDLE 0 -#define CPU_SLEEP_FROZEN 1 -#define CPU_SLEEP_STANDBY 2 -#define CPU_SLEEP_STOP 3 -#define CPU_SLEEP_STATIC 5 - -#ifndef __ASSEMBLY__ -extern void cpu_enter_idle(void); -extern void cpu_enter_standby(unsigned long sdramc_base); - -void intc_set_suspend_handler(unsigned long offset); -#endif - -#endif /* __ASM_AVR32_ARCH_PM_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h deleted file mode 100644 index 4873024e3b96..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/portmux.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * AT32 portmux interface. - * - * Copyright (C) 2006 Atmel Corporation - * - * 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 __ASM_ARCH_PORTMUX_H__ -#define __ASM_ARCH_PORTMUX_H__ - -/* - * Set up pin multiplexing, called from board init only. - * - * The following flags determine the initial state of the pin. - */ -#define AT32_GPIOF_PULLUP 0x00000001 /* (not-OUT) Enable pull-up */ -#define AT32_GPIOF_OUTPUT 0x00000002 /* (OUT) Enable output driver */ -#define AT32_GPIOF_HIGH 0x00000004 /* (OUT) Set output high */ -#define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ -#define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */ - -void at32_select_periph(unsigned int port, unsigned int pin, - unsigned int periph, unsigned long flags); -void at32_select_gpio(unsigned int pin, unsigned long flags); -void at32_deselect_pin(unsigned int pin); -void at32_reserve_pin(unsigned int port, u32 pin_mask); - -#endif /* __ASM_ARCH_PORTMUX_H__ */ diff --git a/arch/avr32/mach-at32ap/include/mach/smc.h b/arch/avr32/mach-at32ap/include/mach/smc.h deleted file mode 100644 index c98eea44a70a..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/smc.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Static Memory Controller for AT32 chips - * - * Copyright (C) 2006 Atmel Corporation - * - * Inspired by the OMAP2 General-Purpose Memory Controller interface - * - * 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 __ARCH_AT32AP_SMC_H -#define __ARCH_AT32AP_SMC_H - -/* - * All timing parameters are in nanoseconds. - */ -struct smc_timing { - /* Delay from address valid to assertion of given strobe */ - int ncs_read_setup; - int nrd_setup; - int ncs_write_setup; - int nwe_setup; - - /* Pulse length of given strobe */ - int ncs_read_pulse; - int nrd_pulse; - int ncs_write_pulse; - int nwe_pulse; - - /* Total cycle length of given operation */ - int read_cycle; - int write_cycle; - - /* Minimal recovery times, will extend cycle if needed */ - int ncs_read_recover; - int nrd_recover; - int ncs_write_recover; - int nwe_recover; -}; - -/* - * All timing parameters are in clock cycles. - */ -struct smc_config { - - /* Delay from address valid to assertion of given strobe */ - u8 ncs_read_setup; - u8 nrd_setup; - u8 ncs_write_setup; - u8 nwe_setup; - - /* Pulse length of given strobe */ - u8 ncs_read_pulse; - u8 nrd_pulse; - u8 ncs_write_pulse; - u8 nwe_pulse; - - /* Total cycle length of given operation */ - u8 read_cycle; - u8 write_cycle; - - /* Bus width in bytes */ - u8 bus_width; - - /* - * 0: Data is sampled on rising edge of NCS - * 1: Data is sampled on rising edge of NRD - */ - unsigned int nrd_controlled:1; - - /* - * 0: Data is driven on falling edge of NCS - * 1: Data is driven on falling edge of NWR - */ - unsigned int nwe_controlled:1; - - /* - * 0: NWAIT is disabled - * 1: Reserved - * 2: NWAIT is frozen mode - * 3: NWAIT in ready mode - */ - unsigned int nwait_mode:2; - - /* - * 0: Byte select access type - * 1: Byte write access type - */ - unsigned int byte_write:1; - - /* - * Number of clock cycles before data is released after - * the rising edge of the read controlling signal - * - * Total cycles from SMC is tdf_cycles + 1 - */ - unsigned int tdf_cycles:4; - - /* - * 0: TDF optimization disabled - * 1: TDF optimization enabled - */ - unsigned int tdf_mode:1; -}; - -extern void smc_set_timing(struct smc_config *config, - const struct smc_timing *timing); - -extern int smc_set_configuration(int cs, const struct smc_config *config); -extern struct smc_config *smc_get_configuration(int cs); - -#endif /* __ARCH_AT32AP_SMC_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/sram.h b/arch/avr32/mach-at32ap/include/mach/sram.h deleted file mode 100644 index 4838dae7601a..000000000000 --- a/arch/avr32/mach-at32ap/include/mach/sram.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Simple SRAM allocator - * - * Copyright (C) 2008 Atmel Corporation - * - * 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 __ASM_AVR32_ARCH_SRAM_H -#define __ASM_AVR32_ARCH_SRAM_H - -#include <linux/genalloc.h> - -extern struct gen_pool *sram_pool; - -static inline unsigned long sram_alloc(size_t len) -{ - if (!sram_pool) - return 0UL; - - return gen_pool_alloc(sram_pool, len); -} - -static inline void sram_free(unsigned long addr, size_t len) -{ - return gen_pool_free(sram_pool, addr, len); -} - -#endif /* __ASM_AVR32_ARCH_SRAM_H */ diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c deleted file mode 100644 index aaff83cc50f0..000000000000 --- a/arch/avr32/mach-at32ap/intc.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Atmel Corporation - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/syscore_ops.h> -#include <linux/export.h> - -#include <asm/io.h> - -#include "intc.h" - -struct intc { - void __iomem *regs; - struct irq_chip chip; -#ifdef CONFIG_PM - unsigned long suspend_ipr; - unsigned long saved_ipr[64]; -#endif -}; - -extern struct platform_device at32_intc0_device; - -/* - * TODO: We may be able to implement mask/unmask by setting IxM flags - * in the status register. - */ -static void intc_mask_irq(struct irq_data *d) -{ - -} - -static void intc_unmask_irq(struct irq_data *d) -{ - -} - -static struct intc intc0 = { - .chip = { - .name = "intc", - .irq_mask = intc_mask_irq, - .irq_unmask = intc_unmask_irq, - }, -}; - -/* - * All interrupts go via intc at some point. - */ -asmlinkage void do_IRQ(int level, struct pt_regs *regs) -{ - struct pt_regs *old_regs; - unsigned int irq; - unsigned long status_reg; - - local_irq_disable(); - - old_regs = set_irq_regs(regs); - - irq_enter(); - - irq = intc_readl(&intc0, INTCAUSE0 - 4 * level); - generic_handle_irq(irq); - - /* - * Clear all interrupt level masks so that we may handle - * interrupts during softirq processing. If this is a nested - * interrupt, interrupts must stay globally disabled until we - * return. - */ - status_reg = sysreg_read(SR); - status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M) - | SYSREG_BIT(I2M) | SYSREG_BIT(I3M)); - sysreg_write(SR, status_reg); - - irq_exit(); - - set_irq_regs(old_regs); -} - -void __init init_IRQ(void) -{ - extern void _evba(void); - extern void irq_level0(void); - struct resource *regs; - struct clk *pclk; - unsigned int i; - u32 offset, readback; - - regs = platform_get_resource(&at32_intc0_device, IORESOURCE_MEM, 0); - if (!regs) { - printk(KERN_EMERG "intc: no mmio resource defined\n"); - goto fail; - } - pclk = clk_get(&at32_intc0_device.dev, "pclk"); - if (IS_ERR(pclk)) { - printk(KERN_EMERG "intc: no clock defined\n"); - goto fail; - } - - clk_enable(pclk); - - intc0.regs = ioremap(regs->start, resource_size(regs)); - if (!intc0.regs) { - printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n", - (unsigned long)regs->start); - goto fail; - } - - /* - * Initialize all interrupts to level 0 (lowest priority). The - * priority level may be changed by calling - * irq_set_priority(). - * - */ - offset = (unsigned long)&irq_level0 - (unsigned long)&_evba; - for (i = 0; i < NR_INTERNAL_IRQS; i++) { - intc_writel(&intc0, INTPR0 + 4 * i, offset); - readback = intc_readl(&intc0, INTPR0 + 4 * i); - if (readback == offset) - irq_set_chip_and_handler(i, &intc0.chip, - handle_simple_irq); - } - - /* Unmask all interrupt levels */ - sysreg_write(SR, (sysreg_read(SR) - & ~(SR_I3M | SR_I2M | SR_I1M | SR_I0M))); - - return; - -fail: - panic("Interrupt controller initialization failed!\n"); -} - -#ifdef CONFIG_PM -void intc_set_suspend_handler(unsigned long offset) -{ - intc0.suspend_ipr = offset; -} - -static int intc_suspend(void) -{ - int i; - - if (unlikely(!irqs_disabled())) { - pr_err("intc_suspend: called with interrupts enabled\n"); - return -EINVAL; - } - - if (unlikely(!intc0.suspend_ipr)) { - pr_err("intc_suspend: suspend_ipr not initialized\n"); - return -EINVAL; - } - - for (i = 0; i < 64; i++) { - intc0.saved_ipr[i] = intc_readl(&intc0, INTPR0 + 4 * i); - intc_writel(&intc0, INTPR0 + 4 * i, intc0.suspend_ipr); - } - - return 0; -} - -static void intc_resume(void) -{ - int i; - - for (i = 0; i < 64; i++) - intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]); -} -#else -#define intc_suspend NULL -#define intc_resume NULL -#endif - -static struct syscore_ops intc_syscore_ops = { - .suspend = intc_suspend, - .resume = intc_resume, -}; - -static int __init intc_init_syscore(void) -{ - register_syscore_ops(&intc_syscore_ops); - - return 0; -} -device_initcall(intc_init_syscore); - -unsigned long intc_get_pending(unsigned int group) -{ - return intc_readl(&intc0, INTREQ0 + 4 * group); -} -EXPORT_SYMBOL_GPL(intc_get_pending); diff --git a/arch/avr32/mach-at32ap/intc.h b/arch/avr32/mach-at32ap/intc.h deleted file mode 100644 index 4d3664e43a8e..000000000000 --- a/arch/avr32/mach-at32ap/intc.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Automatically generated by gen-header.xsl - */ -#ifndef __ASM_AVR32_PERIHP_INTC_H__ -#define __ASM_AVR32_PERIHP_INTC_H__ - -#define INTC_NUM_INT_GRPS 33 - -#define INTC_INTPR0 0x0 -# define INTC_INTPR0_INTLEV_OFFSET 30 -# define INTC_INTPR0_INTLEV_SIZE 2 -# define INTC_INTPR0_OFFSET_OFFSET 0 -# define INTC_INTPR0_OFFSET_SIZE 24 -#define INTC_INTREQ0 0x100 -# define INTC_INTREQ0_IREQUEST0_OFFSET 0 -# define INTC_INTREQ0_IREQUEST0_SIZE 1 -# define INTC_INTREQ0_IREQUEST1_OFFSET 1 -# define INTC_INTREQ0_IREQUEST1_SIZE 1 -#define INTC_INTPR1 0x4 -# define INTC_INTPR1_INTLEV_OFFSET 30 -# define INTC_INTPR1_INTLEV_SIZE 2 -# define INTC_INTPR1_OFFSET_OFFSET 0 -# define INTC_INTPR1_OFFSET_SIZE 24 -#define INTC_INTREQ1 0x104 -# define INTC_INTREQ1_IREQUEST32_OFFSET 0 -# define INTC_INTREQ1_IREQUEST32_SIZE 1 -# define INTC_INTREQ1_IREQUEST33_OFFSET 1 -# define INTC_INTREQ1_IREQUEST33_SIZE 1 -# define INTC_INTREQ1_IREQUEST34_OFFSET 2 -# define INTC_INTREQ1_IREQUEST34_SIZE 1 -# define INTC_INTREQ1_IREQUEST35_OFFSET 3 -# define INTC_INTREQ1_IREQUEST35_SIZE 1 -# define INTC_INTREQ1_IREQUEST36_OFFSET 4 -# define INTC_INTREQ1_IREQUEST36_SIZE 1 -# define INTC_INTREQ1_IREQUEST37_OFFSET 5 -# define INTC_INTREQ1_IREQUEST37_SIZE 1 -#define INTC_INTPR2 0x8 -# define INTC_INTPR2_INTLEV_OFFSET 30 -# define INTC_INTPR2_INTLEV_SIZE 2 -# define INTC_INTPR2_OFFSET_OFFSET 0 -# define INTC_INTPR2_OFFSET_SIZE 24 -#define INTC_INTREQ2 0x108 -# define INTC_INTREQ2_IREQUEST64_OFFSET 0 -# define INTC_INTREQ2_IREQUEST64_SIZE 1 -# define INTC_INTREQ2_IREQUEST65_OFFSET 1 -# define INTC_INTREQ2_IREQUEST65_SIZE 1 -# define INTC_INTREQ2_IREQUEST66_OFFSET 2 -# define INTC_INTREQ2_IREQUEST66_SIZE 1 -# define INTC_INTREQ2_IREQUEST67_OFFSET 3 -# define INTC_INTREQ2_IREQUEST67_SIZE 1 -# define INTC_INTREQ2_IREQUEST68_OFFSET 4 -# define INTC_INTREQ2_IREQUEST68_SIZE 1 -#define INTC_INTPR3 0xc -# define INTC_INTPR3_INTLEV_OFFSET 30 -# define INTC_INTPR3_INTLEV_SIZE 2 -# define INTC_INTPR3_OFFSET_OFFSET 0 -# define INTC_INTPR3_OFFSET_SIZE 24 -#define INTC_INTREQ3 0x10c -# define INTC_INTREQ3_IREQUEST96_OFFSET 0 -# define INTC_INTREQ3_IREQUEST96_SIZE 1 -#define INTC_INTPR4 0x10 -# define INTC_INTPR4_INTLEV_OFFSET 30 -# define INTC_INTPR4_INTLEV_SIZE 2 -# define INTC_INTPR4_OFFSET_OFFSET 0 -# define INTC_INTPR4_OFFSET_SIZE 24 -#define INTC_INTREQ4 0x110 -# define INTC_INTREQ4_IREQUEST128_OFFSET 0 -# define INTC_INTREQ4_IREQUEST128_SIZE 1 -#define INTC_INTPR5 0x14 -# define INTC_INTPR5_INTLEV_OFFSET 30 -# define INTC_INTPR5_INTLEV_SIZE 2 -# define INTC_INTPR5_OFFSET_OFFSET 0 -# define INTC_INTPR5_OFFSET_SIZE 24 -#define INTC_INTREQ5 0x114 -# define INTC_INTREQ5_IREQUEST160_OFFSET 0 -# define INTC_INTREQ5_IREQUEST160_SIZE 1 -#define INTC_INTPR6 0x18 -# define INTC_INTPR6_INTLEV_OFFSET 30 -# define INTC_INTPR6_INTLEV_SIZE 2 -# define INTC_INTPR6_OFFSET_OFFSET 0 -# define INTC_INTPR6_OFFSET_SIZE 24 -#define INTC_INTREQ6 0x118 -# define INTC_INTREQ6_IREQUEST192_OFFSET 0 -# define INTC_INTREQ6_IREQUEST192_SIZE 1 -#define INTC_INTPR7 0x1c -# define INTC_INTPR7_INTLEV_OFFSET 30 -# define INTC_INTPR7_INTLEV_SIZE 2 -# define INTC_INTPR7_OFFSET_OFFSET 0 -# define INTC_INTPR7_OFFSET_SIZE 24 -#define INTC_INTREQ7 0x11c -# define INTC_INTREQ7_IREQUEST224_OFFSET 0 -# define INTC_INTREQ7_IREQUEST224_SIZE 1 -#define INTC_INTPR8 0x20 -# define INTC_INTPR8_INTLEV_OFFSET 30 -# define INTC_INTPR8_INTLEV_SIZE 2 -# define INTC_INTPR8_OFFSET_OFFSET 0 -# define INTC_INTPR8_OFFSET_SIZE 24 -#define INTC_INTREQ8 0x120 -# define INTC_INTREQ8_IREQUEST256_OFFSET 0 -# define INTC_INTREQ8_IREQUEST256_SIZE 1 -#define INTC_INTPR9 0x24 -# define INTC_INTPR9_INTLEV_OFFSET 30 -# define INTC_INTPR9_INTLEV_SIZE 2 -# define INTC_INTPR9_OFFSET_OFFSET 0 -# define INTC_INTPR9_OFFSET_SIZE 24 -#define INTC_INTREQ9 0x124 -# define INTC_INTREQ9_IREQUEST288_OFFSET 0 -# define INTC_INTREQ9_IREQUEST288_SIZE 1 -#define INTC_INTPR10 0x28 -# define INTC_INTPR10_INTLEV_OFFSET 30 -# define INTC_INTPR10_INTLEV_SIZE 2 -# define INTC_INTPR10_OFFSET_OFFSET 0 -# define INTC_INTPR10_OFFSET_SIZE 24 -#define INTC_INTREQ10 0x128 -# define INTC_INTREQ10_IREQUEST320_OFFSET 0 -# define INTC_INTREQ10_IREQUEST320_SIZE 1 -#define INTC_INTPR11 0x2c -# define INTC_INTPR11_INTLEV_OFFSET 30 -# define INTC_INTPR11_INTLEV_SIZE 2 -# define INTC_INTPR11_OFFSET_OFFSET 0 -# define INTC_INTPR11_OFFSET_SIZE 24 -#define INTC_INTREQ11 0x12c -# define INTC_INTREQ11_IREQUEST352_OFFSET 0 -# define INTC_INTREQ11_IREQUEST352_SIZE 1 -#define INTC_INTPR12 0x30 -# define INTC_INTPR12_INTLEV_OFFSET 30 -# define INTC_INTPR12_INTLEV_SIZE 2 -# define INTC_INTPR12_OFFSET_OFFSET 0 -# define INTC_INTPR12_OFFSET_SIZE 24 -#define INTC_INTREQ12 0x130 -# define INTC_INTREQ12_IREQUEST384_OFFSET 0 -# define INTC_INTREQ12_IREQUEST384_SIZE 1 -#define INTC_INTPR13 0x34 -# define INTC_INTPR13_INTLEV_OFFSET 30 -# define INTC_INTPR13_INTLEV_SIZE 2 -# define INTC_INTPR13_OFFSET_OFFSET 0 -# define INTC_INTPR13_OFFSET_SIZE 24 -#define INTC_INTREQ13 0x134 -# define INTC_INTREQ13_IREQUEST416_OFFSET 0 -# define INTC_INTREQ13_IREQUEST416_SIZE 1 -#define INTC_INTPR14 0x38 -# define INTC_INTPR14_INTLEV_OFFSET 30 -# define INTC_INTPR14_INTLEV_SIZE 2 -# define INTC_INTPR14_OFFSET_OFFSET 0 -# define INTC_INTPR14_OFFSET_SIZE 24 -#define INTC_INTREQ14 0x138 -# define INTC_INTREQ14_IREQUEST448_OFFSET 0 -# define INTC_INTREQ14_IREQUEST448_SIZE 1 -#define INTC_INTPR15 0x3c -# define INTC_INTPR15_INTLEV_OFFSET 30 -# define INTC_INTPR15_INTLEV_SIZE 2 -# define INTC_INTPR15_OFFSET_OFFSET 0 -# define INTC_INTPR15_OFFSET_SIZE 24 -#define INTC_INTREQ15 0x13c -# define INTC_INTREQ15_IREQUEST480_OFFSET 0 -# define INTC_INTREQ15_IREQUEST480_SIZE 1 -#define INTC_INTPR16 0x40 -# define INTC_INTPR16_INTLEV_OFFSET 30 -# define INTC_INTPR16_INTLEV_SIZE 2 -# define INTC_INTPR16_OFFSET_OFFSET 0 -# define INTC_INTPR16_OFFSET_SIZE 24 -#define INTC_INTREQ16 0x140 -# define INTC_INTREQ16_IREQUEST512_OFFSET 0 -# define INTC_INTREQ16_IREQUEST512_SIZE 1 -#define INTC_INTPR17 0x44 -# define INTC_INTPR17_INTLEV_OFFSET 30 -# define INTC_INTPR17_INTLEV_SIZE 2 -# define INTC_INTPR17_OFFSET_OFFSET 0 -# define INTC_INTPR17_OFFSET_SIZE 24 -#define INTC_INTREQ17 0x144 -# define INTC_INTREQ17_IREQUEST544_OFFSET 0 -# define INTC_INTREQ17_IREQUEST544_SIZE 1 -#define INTC_INTPR18 0x48 -# define INTC_INTPR18_INTLEV_OFFSET 30 -# define INTC_INTPR18_INTLEV_SIZE 2 -# define INTC_INTPR18_OFFSET_OFFSET 0 -# define INTC_INTPR18_OFFSET_SIZE 24 -#define INTC_INTREQ18 0x148 -# define INTC_INTREQ18_IREQUEST576_OFFSET 0 -# define INTC_INTREQ18_IREQUEST576_SIZE 1 -#define INTC_INTPR19 0x4c -# define INTC_INTPR19_INTLEV_OFFSET 30 -# define INTC_INTPR19_INTLEV_SIZE 2 -# define INTC_INTPR19_OFFSET_OFFSET 0 -# define INTC_INTPR19_OFFSET_SIZE 24 -#define INTC_INTREQ19 0x14c -# define INTC_INTREQ19_IREQUEST608_OFFSET 0 -# define INTC_INTREQ19_IREQUEST608_SIZE 1 -# define INTC_INTREQ19_IREQUEST609_OFFSET 1 -# define INTC_INTREQ19_IREQUEST609_SIZE 1 -# define INTC_INTREQ19_IREQUEST610_OFFSET 2 -# define INTC_INTREQ19_IREQUEST610_SIZE 1 -# define INTC_INTREQ19_IREQUEST611_OFFSET 3 -# define INTC_INTREQ19_IREQUEST611_SIZE 1 -#define INTC_INTPR20 0x50 -# define INTC_INTPR20_INTLEV_OFFSET 30 -# define INTC_INTPR20_INTLEV_SIZE 2 -# define INTC_INTPR20_OFFSET_OFFSET 0 -# define INTC_INTPR20_OFFSET_SIZE 24 -#define INTC_INTREQ20 0x150 -# define INTC_INTREQ20_IREQUEST640_OFFSET 0 -# define INTC_INTREQ20_IREQUEST640_SIZE 1 -#define INTC_INTPR21 0x54 -# define INTC_INTPR21_INTLEV_OFFSET 30 -# define INTC_INTPR21_INTLEV_SIZE 2 -# define INTC_INTPR21_OFFSET_OFFSET 0 -# define INTC_INTPR21_OFFSET_SIZE 24 -#define INTC_INTREQ21 0x154 -# define INTC_INTREQ21_IREQUEST672_OFFSET 0 -# define INTC_INTREQ21_IREQUEST672_SIZE 1 -#define INTC_INTPR22 0x58 -# define INTC_INTPR22_INTLEV_OFFSET 30 -# define INTC_INTPR22_INTLEV_SIZE 2 -# define INTC_INTPR22_OFFSET_OFFSET 0 -# define INTC_INTPR22_OFFSET_SIZE 24 -#define INTC_INTREQ22 0x158 -# define INTC_INTREQ22_IREQUEST704_OFFSET 0 -# define INTC_INTREQ22_IREQUEST704_SIZE 1 -# define INTC_INTREQ22_IREQUEST705_OFFSET 1 -# define INTC_INTREQ22_IREQUEST705_SIZE 1 -# define INTC_INTREQ22_IREQUEST706_OFFSET 2 -# define INTC_INTREQ22_IREQUEST706_SIZE 1 -#define INTC_INTPR23 0x5c -# define INTC_INTPR23_INTLEV_OFFSET 30 -# define INTC_INTPR23_INTLEV_SIZE 2 -# define INTC_INTPR23_OFFSET_OFFSET 0 -# define INTC_INTPR23_OFFSET_SIZE 24 -#define INTC_INTREQ23 0x15c -# define INTC_INTREQ23_IREQUEST736_OFFSET 0 -# define INTC_INTREQ23_IREQUEST736_SIZE 1 -# define INTC_INTREQ23_IREQUEST737_OFFSET 1 -# define INTC_INTREQ23_IREQUEST737_SIZE 1 -# define INTC_INTREQ23_IREQUEST738_OFFSET 2 -# define INTC_INTREQ23_IREQUEST738_SIZE 1 -#define INTC_INTPR24 0x60 -# define INTC_INTPR24_INTLEV_OFFSET 30 -# define INTC_INTPR24_INTLEV_SIZE 2 -# define INTC_INTPR24_OFFSET_OFFSET 0 -# define INTC_INTPR24_OFFSET_SIZE 24 -#define INTC_INTREQ24 0x160 -# define INTC_INTREQ24_IREQUEST768_OFFSET 0 -# define INTC_INTREQ24_IREQUEST768_SIZE 1 -#define INTC_INTPR25 0x64 -# define INTC_INTPR25_INTLEV_OFFSET 30 -# define INTC_INTPR25_INTLEV_SIZE 2 -# define INTC_INTPR25_OFFSET_OFFSET 0 -# define INTC_INTPR25_OFFSET_SIZE 24 -#define INTC_INTREQ25 0x164 -# define INTC_INTREQ25_IREQUEST800_OFFSET 0 -# define INTC_INTREQ25_IREQUEST800_SIZE 1 -#define INTC_INTPR26 0x68 -# define INTC_INTPR26_INTLEV_OFFSET 30 -# define INTC_INTPR26_INTLEV_SIZE 2 -# define INTC_INTPR26_OFFSET_OFFSET 0 -# define INTC_INTPR26_OFFSET_SIZE 24 -#define INTC_INTREQ26 0x168 -# define INTC_INTREQ26_IREQUEST832_OFFSET 0 -# define INTC_INTREQ26_IREQUEST832_SIZE 1 -#define INTC_INTPR27 0x6c -# define INTC_INTPR27_INTLEV_OFFSET 30 -# define INTC_INTPR27_INTLEV_SIZE 2 -# define INTC_INTPR27_OFFSET_OFFSET 0 -# define INTC_INTPR27_OFFSET_SIZE 24 -#define INTC_INTREQ27 0x16c -# define INTC_INTREQ27_IREQUEST864_OFFSET 0 -# define INTC_INTREQ27_IREQUEST864_SIZE 1 -#define INTC_INTPR28 0x70 -# define INTC_INTPR28_INTLEV_OFFSET 30 -# define INTC_INTPR28_INTLEV_SIZE 2 -# define INTC_INTPR28_OFFSET_OFFSET 0 -# define INTC_INTPR28_OFFSET_SIZE 24 -#define INTC_INTREQ28 0x170 -# define INTC_INTREQ28_IREQUEST896_OFFSET 0 -# define INTC_INTREQ28_IREQUEST896_SIZE 1 -#define INTC_INTPR29 0x74 -# define INTC_INTPR29_INTLEV_OFFSET 30 -# define INTC_INTPR29_INTLEV_SIZE 2 -# define INTC_INTPR29_OFFSET_OFFSET 0 -# define INTC_INTPR29_OFFSET_SIZE 24 -#define INTC_INTREQ29 0x174 -# define INTC_INTREQ29_IREQUEST928_OFFSET 0 -# define INTC_INTREQ29_IREQUEST928_SIZE 1 -#define INTC_INTPR30 0x78 -# define INTC_INTPR30_INTLEV_OFFSET 30 -# define INTC_INTPR30_INTLEV_SIZE 2 -# define INTC_INTPR30_OFFSET_OFFSET 0 -# define INTC_INTPR30_OFFSET_SIZE 24 -#define INTC_INTREQ30 0x178 -# define INTC_INTREQ30_IREQUEST960_OFFSET 0 -# define INTC_INTREQ30_IREQUEST960_SIZE 1 -#define INTC_INTPR31 0x7c -# define INTC_INTPR31_INTLEV_OFFSET 30 -# define INTC_INTPR31_INTLEV_SIZE 2 -# define INTC_INTPR31_OFFSET_OFFSET 0 -# define INTC_INTPR31_OFFSET_SIZE 24 -#define INTC_INTREQ31 0x17c -# define INTC_INTREQ31_IREQUEST992_OFFSET 0 -# define INTC_INTREQ31_IREQUEST992_SIZE 1 -#define INTC_INTPR32 0x80 -# define INTC_INTPR32_INTLEV_OFFSET 30 -# define INTC_INTPR32_INTLEV_SIZE 2 -# define INTC_INTPR32_OFFSET_OFFSET 0 -# define INTC_INTPR32_OFFSET_SIZE 24 -#define INTC_INTREQ32 0x180 -# define INTC_INTREQ32_IREQUEST1024_OFFSET 0 -# define INTC_INTREQ32_IREQUEST1024_SIZE 1 -#define INTC_INTCAUSE0 0x20c -# define INTC_INTCAUSE0_CAUSEGRP_OFFSET 0 -# define INTC_INTCAUSE0_CAUSEGRP_SIZE 6 -#define INTC_INTCAUSE1 0x208 -# define INTC_INTCAUSE1_CAUSEGRP_OFFSET 0 -# define INTC_INTCAUSE1_CAUSEGRP_SIZE 6 -#define INTC_INTCAUSE2 0x204 -# define INTC_INTCAUSE2_CAUSEGRP_OFFSET 0 -# define INTC_INTCAUSE2_CAUSEGRP_SIZE 6 -#define INTC_INTCAUSE3 0x200 -# define INTC_INTCAUSE3_CAUSEGRP_OFFSET 0 -# define INTC_INTCAUSE3_CAUSEGRP_SIZE 6 - -#define INTC_BIT(name) (1 << INTC_##name##_OFFSET) -#define INTC_MKBF(name, value) (((value) & ((1 << INTC_##name##_SIZE) - 1)) << INTC_##name##_OFFSET) -#define INTC_GETBF(name, value) (((value) >> INTC_##name##_OFFSET) & ((1 << INTC_##name##_SIZE) - 1)) - -#define intc_readl(port,reg) \ - __raw_readl((port)->regs + INTC_##reg) -#define intc_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + INTC_##reg) - -#endif /* __ASM_AVR32_PERIHP_INTC_H__ */ diff --git a/arch/avr32/mach-at32ap/pdc.c b/arch/avr32/mach-at32ap/pdc.c deleted file mode 100644 index 61ab15aae970..000000000000 --- a/arch/avr32/mach-at32ap/pdc.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2006 Atmel Corporation - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/platform_device.h> - -static int __init pdc_probe(struct platform_device *pdev) -{ - struct clk *pclk, *hclk; - - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) { - dev_err(&pdev->dev, "no pclk defined\n"); - return PTR_ERR(pclk); - } - hclk = clk_get(&pdev->dev, "hclk"); - if (IS_ERR(hclk)) { - dev_err(&pdev->dev, "no hclk defined\n"); - clk_put(pclk); - return PTR_ERR(hclk); - } - - clk_enable(pclk); - clk_enable(hclk); - - dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n"); - return 0; -} - -static struct platform_driver pdc_driver = { - .driver = { - .name = "pdc", - }, -}; - -static int __init pdc_init(void) -{ - return platform_driver_probe(&pdc_driver, pdc_probe); -} -arch_initcall(pdc_init); diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c deleted file mode 100644 index 7fae6ec7e8ec..000000000000 --- a/arch/avr32/mach-at32ap/pio.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Atmel PIO2 Port Multiplexer support - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/clk.h> -#include <linux/debugfs.h> -#include <linux/export.h> -#include <linux/fs.h> -#include <linux/platform_device.h> -#include <linux/irq.h> -#include <linux/gpio.h> - -#include <asm/io.h> - -#include <mach/portmux.h> - -#include "pio.h" - -#define MAX_NR_PIO_DEVICES 8 - -struct pio_device { - struct gpio_chip chip; - void __iomem *regs; - const struct platform_device *pdev; - struct clk *clk; - u32 pinmux_mask; - char name[8]; -}; - -static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; - -static struct pio_device *gpio_to_pio(unsigned int gpio) -{ - struct pio_device *pio; - unsigned int index; - - index = gpio >> 5; - if (index >= MAX_NR_PIO_DEVICES) - return NULL; - pio = &pio_dev[index]; - if (!pio->regs) - return NULL; - - return pio; -} - -/* Pin multiplexing API */ -static DEFINE_SPINLOCK(pio_lock); - -void __init at32_select_periph(unsigned int port, u32 pin_mask, - unsigned int periph, unsigned long flags) -{ - struct pio_device *pio; - - /* assign and verify pio */ - pio = gpio_to_pio(port); - if (unlikely(!pio)) { - printk(KERN_WARNING "pio: invalid port %u\n", port); - goto fail; - } - - /* Test if any of the requested pins is already muxed */ - spin_lock(&pio_lock); - if (unlikely(pio->pinmux_mask & pin_mask)) { - printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n", - pio->name, pin_mask, pio->pinmux_mask & pin_mask); - spin_unlock(&pio_lock); - goto fail; - } - - pio->pinmux_mask |= pin_mask; - - /* enable pull ups */ - pio_writel(pio, PUER, pin_mask); - - /* select either peripheral A or B */ - if (periph) - pio_writel(pio, BSR, pin_mask); - else - pio_writel(pio, ASR, pin_mask); - - /* enable peripheral control */ - pio_writel(pio, PDR, pin_mask); - - /* Disable pull ups if not requested. */ - if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, pin_mask); - - spin_unlock(&pio_lock); - - return; - -fail: - dump_stack(); -} - -void __init at32_select_gpio(unsigned int pin, unsigned long flags) -{ - struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - u32 mask = 1 << pin_index; - - pio = gpio_to_pio(pin); - if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); - goto fail; - } - - if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { - printk("%s: pin %u is busy\n", pio->name, pin_index); - goto fail; - } - - if (flags & AT32_GPIOF_OUTPUT) { - if (flags & AT32_GPIOF_HIGH) - pio_writel(pio, SODR, mask); - else - pio_writel(pio, CODR, mask); - if (flags & AT32_GPIOF_MULTIDRV) - pio_writel(pio, MDER, mask); - else - pio_writel(pio, MDDR, mask); - pio_writel(pio, PUDR, mask); - pio_writel(pio, OER, mask); - } else { - if (flags & AT32_GPIOF_PULLUP) - pio_writel(pio, PUER, mask); - else - pio_writel(pio, PUDR, mask); - if (flags & AT32_GPIOF_DEGLITCH) - pio_writel(pio, IFER, mask); - else - pio_writel(pio, IFDR, mask); - pio_writel(pio, ODR, mask); - } - - pio_writel(pio, PER, mask); - - return; - -fail: - dump_stack(); -} - -/* - * Undo a previous pin reservation. Will not affect the hardware - * configuration. - */ -void at32_deselect_pin(unsigned int pin) -{ - struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - - pio = gpio_to_pio(pin); - if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); - dump_stack(); - return; - } - - clear_bit(pin_index, &pio->pinmux_mask); -} - -/* Reserve a pin, preventing anyone else from changing its configuration. */ -void __init at32_reserve_pin(unsigned int port, u32 pin_mask) -{ - struct pio_device *pio; - - /* assign and verify pio */ - pio = gpio_to_pio(port); - if (unlikely(!pio)) { - printk(KERN_WARNING "pio: invalid port %u\n", port); - goto fail; - } - - /* Test if any of the requested pins is already muxed */ - spin_lock(&pio_lock); - if (unlikely(pio->pinmux_mask & pin_mask)) { - printk(KERN_WARNING "%s: pin(s) busy (req. 0x%x, busy 0x%x)\n", - pio->name, pin_mask, pio->pinmux_mask & pin_mask); - spin_unlock(&pio_lock); - goto fail; - } - - /* Reserve pins */ - pio->pinmux_mask |= pin_mask; - spin_unlock(&pio_lock); - return; - -fail: - dump_stack(); -} - -/*--------------------------------------------------------------------------*/ - -/* GPIO API */ - -static int direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct pio_device *pio = gpiochip_get_data(chip); - u32 mask = 1 << offset; - - if (!(pio_readl(pio, PSR) & mask)) - return -EINVAL; - - pio_writel(pio, ODR, mask); - return 0; -} - -static int gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct pio_device *pio = gpiochip_get_data(chip); - - return (pio_readl(pio, PDSR) >> offset) & 1; -} - -static void gpio_set(struct gpio_chip *chip, unsigned offset, int value); - -static int direction_output(struct gpio_chip *chip, unsigned offset, int value) -{ - struct pio_device *pio = gpiochip_get_data(chip); - u32 mask = 1 << offset; - - if (!(pio_readl(pio, PSR) & mask)) - return -EINVAL; - - gpio_set(chip, offset, value); - pio_writel(pio, OER, mask); - return 0; -} - -static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct pio_device *pio = gpiochip_get_data(chip); - u32 mask = 1 << offset; - - if (value) - pio_writel(pio, SODR, mask); - else - pio_writel(pio, CODR, mask); -} - -/*--------------------------------------------------------------------------*/ - -/* GPIO IRQ support */ - -static void gpio_irq_mask(struct irq_data *d) -{ - unsigned gpio = irq_to_gpio(d->irq); - struct pio_device *pio = &pio_dev[gpio >> 5]; - - pio_writel(pio, IDR, 1 << (gpio & 0x1f)); -} - -static void gpio_irq_unmask(struct irq_data *d) -{ - unsigned gpio = irq_to_gpio(d->irq); - struct pio_device *pio = &pio_dev[gpio >> 5]; - - pio_writel(pio, IER, 1 << (gpio & 0x1f)); -} - -static int gpio_irq_type(struct irq_data *d, unsigned type) -{ - if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE) - return -EINVAL; - - return 0; -} - -static struct irq_chip gpio_irqchip = { - .name = "gpio", - .irq_mask = gpio_irq_mask, - .irq_unmask = gpio_irq_unmask, - .irq_set_type = gpio_irq_type, -}; - -static void gpio_irq_handler(struct irq_desc *desc) -{ - struct pio_device *pio = irq_desc_get_chip_data(desc); - unsigned gpio_irq; - - gpio_irq = (unsigned) irq_desc_get_handler_data(desc); - for (;;) { - u32 isr; - - /* ack pending GPIO interrupts */ - isr = pio_readl(pio, ISR) & pio_readl(pio, IMR); - if (!isr) - break; - do { - int i; - - i = ffs(isr) - 1; - isr &= ~(1 << i); - - i += gpio_irq; - generic_handle_irq(i); - } while (isr); - } -} - -static void __init -gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq) -{ - unsigned i; - - irq_set_chip_data(irq, pio); - - for (i = 0; i < 32; i++, gpio_irq++) { - irq_set_chip_data(gpio_irq, pio); - irq_set_chip_and_handler(gpio_irq, &gpio_irqchip, - handle_simple_irq); - } - - irq_set_chained_handler_and_data(irq, gpio_irq_handler, - (void *)gpio_irq); -} - -/*--------------------------------------------------------------------------*/ - -#ifdef CONFIG_DEBUG_FS - -#include <linux/seq_file.h> - -/* - * This shows more info than the generic gpio dump code: - * pullups, deglitching, open drain drive. - */ -static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct pio_device *pio = gpiochip_get_data(chip); - u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr; - unsigned i; - u32 mask; - char bank; - - psr = pio_readl(pio, PSR); - osr = pio_readl(pio, OSR); - imr = pio_readl(pio, IMR); - pdsr = pio_readl(pio, PDSR); - pusr = pio_readl(pio, PUSR); - ifsr = pio_readl(pio, IFSR); - mdsr = pio_readl(pio, MDSR); - - bank = 'A' + pio->pdev->id; - - for (i = 0, mask = 1; i < 32; i++, mask <<= 1) { - const char *label; - - label = gpiochip_is_requested(chip, i); - if (!label && (imr & mask)) - label = "[irq]"; - if (!label) - continue; - - seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s", - chip->base + i, bank, i, - label, - (osr & mask) ? "out" : "in ", - (mask & pdsr) ? "hi" : "lo", - (mask & pusr) ? " " : "up"); - if (ifsr & mask) - seq_puts(s, " deglitch"); - if ((osr & mdsr) & mask) - seq_puts(s, " open-drain"); - if (imr & mask) - seq_printf(s, " irq-%d edge-both", - gpio_to_irq(chip->base + i)); - seq_putc(s, '\n'); - } -} - -#else -#define pio_bank_show NULL -#endif - - -/*--------------------------------------------------------------------------*/ - -static int __init pio_probe(struct platform_device *pdev) -{ - struct pio_device *pio = NULL; - int irq = platform_get_irq(pdev, 0); - int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32; - - BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES); - pio = &pio_dev[pdev->id]; - BUG_ON(!pio->regs); - - pio->chip.label = pio->name; - pio->chip.base = pdev->id * 32; - pio->chip.ngpio = 32; - pio->chip.parent = &pdev->dev; - pio->chip.owner = THIS_MODULE; - - pio->chip.direction_input = direction_input; - pio->chip.get = gpio_get; - pio->chip.direction_output = direction_output; - pio->chip.set = gpio_set; - pio->chip.dbg_show = pio_bank_show; - - gpiochip_add_data(&pio->chip, pio); - - gpio_irq_setup(pio, irq, gpio_irq_base); - - platform_set_drvdata(pdev, pio); - - printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n", - pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31); - - return 0; -} - -static struct platform_driver pio_driver = { - .driver = { - .name = "pio", - }, -}; - -static int __init pio_init(void) -{ - return platform_driver_probe(&pio_driver, pio_probe); -} -postcore_initcall(pio_init); - -void __init at32_init_pio(struct platform_device *pdev) -{ - struct resource *regs; - struct pio_device *pio; - - if (pdev->id >= MAX_NR_PIO_DEVICES) { - dev_err(&pdev->dev, "only %d PIO devices supported\n", - MAX_NR_PIO_DEVICES); - return; - } - - pio = &pio_dev[pdev->id]; - snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id); - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_err(&pdev->dev, "no mmio resource defined\n"); - return; - } - - pio->clk = clk_get(&pdev->dev, "mck"); - if (IS_ERR(pio->clk)) - /* - * This is a fatal error, but if we continue we might - * be so lucky that we manage to initialize the - * console and display this message... - */ - dev_err(&pdev->dev, "no mck clock defined\n"); - else - clk_enable(pio->clk); - - pio->pdev = pdev; - pio->regs = ioremap(regs->start, resource_size(regs)); - - /* start with irqs disabled and acked */ - pio_writel(pio, IDR, ~0UL); - (void) pio_readl(pio, ISR); -} diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h deleted file mode 100644 index 9484dfcc08f2..000000000000 --- a/arch/avr32/mach-at32ap/pio.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Atmel PIO2 Port Multiplexer support - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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 __ARCH_AVR32_AT32AP_PIO_H__ -#define __ARCH_AVR32_AT32AP_PIO_H__ - -/* PIO register offsets */ -#define PIO_PER 0x0000 -#define PIO_PDR 0x0004 -#define PIO_PSR 0x0008 -#define PIO_OER 0x0010 -#define PIO_ODR 0x0014 -#define PIO_OSR 0x0018 -#define PIO_IFER 0x0020 -#define PIO_IFDR 0x0024 -#define PIO_IFSR 0x0028 -#define PIO_SODR 0x0030 -#define PIO_CODR 0x0034 -#define PIO_ODSR 0x0038 -#define PIO_PDSR 0x003c -#define PIO_IER 0x0040 -#define PIO_IDR 0x0044 -#define PIO_IMR 0x0048 -#define PIO_ISR 0x004c -#define PIO_MDER 0x0050 -#define PIO_MDDR 0x0054 -#define PIO_MDSR 0x0058 -#define PIO_PUDR 0x0060 -#define PIO_PUER 0x0064 -#define PIO_PUSR 0x0068 -#define PIO_ASR 0x0070 -#define PIO_BSR 0x0074 -#define PIO_ABSR 0x0078 -#define PIO_OWER 0x00a0 -#define PIO_OWDR 0x00a4 -#define PIO_OWSR 0x00a8 - -/* Bitfields in PER */ - -/* Bitfields in PDR */ - -/* Bitfields in PSR */ - -/* Bitfields in OER */ - -/* Bitfields in ODR */ - -/* Bitfields in OSR */ - -/* Bitfields in IFER */ - -/* Bitfields in IFDR */ - -/* Bitfields in IFSR */ - -/* Bitfields in SODR */ - -/* Bitfields in CODR */ - -/* Bitfields in ODSR */ - -/* Bitfields in PDSR */ - -/* Bitfields in IER */ - -/* Bitfields in IDR */ - -/* Bitfields in IMR */ - -/* Bitfields in ISR */ - -/* Bitfields in MDER */ - -/* Bitfields in MDDR */ - -/* Bitfields in MDSR */ - -/* Bitfields in PUDR */ - -/* Bitfields in PUER */ - -/* Bitfields in PUSR */ - -/* Bitfields in ASR */ - -/* Bitfields in BSR */ - -/* Bitfields in ABSR */ -#define PIO_P0_OFFSET 0 -#define PIO_P0_SIZE 1 -#define PIO_P1_OFFSET 1 -#define PIO_P1_SIZE 1 -#define PIO_P2_OFFSET 2 -#define PIO_P2_SIZE 1 -#define PIO_P3_OFFSET 3 -#define PIO_P3_SIZE 1 -#define PIO_P4_OFFSET 4 -#define PIO_P4_SIZE 1 -#define PIO_P5_OFFSET 5 -#define PIO_P5_SIZE 1 -#define PIO_P6_OFFSET 6 -#define PIO_P6_SIZE 1 -#define PIO_P7_OFFSET 7 -#define PIO_P7_SIZE 1 -#define PIO_P8_OFFSET 8 -#define PIO_P8_SIZE 1 -#define PIO_P9_OFFSET 9 -#define PIO_P9_SIZE 1 -#define PIO_P10_OFFSET 10 -#define PIO_P10_SIZE 1 -#define PIO_P11_OFFSET 11 -#define PIO_P11_SIZE 1 -#define PIO_P12_OFFSET 12 -#define PIO_P12_SIZE 1 -#define PIO_P13_OFFSET 13 -#define PIO_P13_SIZE 1 -#define PIO_P14_OFFSET 14 -#define PIO_P14_SIZE 1 -#define PIO_P15_OFFSET 15 -#define PIO_P15_SIZE 1 -#define PIO_P16_OFFSET 16 -#define PIO_P16_SIZE 1 -#define PIO_P17_OFFSET 17 -#define PIO_P17_SIZE 1 -#define PIO_P18_OFFSET 18 -#define PIO_P18_SIZE 1 -#define PIO_P19_OFFSET 19 -#define PIO_P19_SIZE 1 -#define PIO_P20_OFFSET 20 -#define PIO_P20_SIZE 1 -#define PIO_P21_OFFSET 21 -#define PIO_P21_SIZE 1 -#define PIO_P22_OFFSET 22 -#define PIO_P22_SIZE 1 -#define PIO_P23_OFFSET 23 -#define PIO_P23_SIZE 1 -#define PIO_P24_OFFSET 24 -#define PIO_P24_SIZE 1 -#define PIO_P25_OFFSET 25 -#define PIO_P25_SIZE 1 -#define PIO_P26_OFFSET 26 -#define PIO_P26_SIZE 1 -#define PIO_P27_OFFSET 27 -#define PIO_P27_SIZE 1 -#define PIO_P28_OFFSET 28 -#define PIO_P28_SIZE 1 -#define PIO_P29_OFFSET 29 -#define PIO_P29_SIZE 1 -#define PIO_P30_OFFSET 30 -#define PIO_P30_SIZE 1 -#define PIO_P31_OFFSET 31 -#define PIO_P31_SIZE 1 - -/* Bitfields in OWER */ - -/* Bitfields in OWDR */ - -/* Bitfields in OWSR */ - -/* Bit manipulation macros */ -#define PIO_BIT(name) (1 << PIO_##name##_OFFSET) -#define PIO_BF(name,value) (((value) & ((1 << PIO_##name##_SIZE) - 1)) << PIO_##name##_OFFSET) -#define PIO_BFEXT(name,value) (((value) >> PIO_##name##_OFFSET) & ((1 << PIO_##name##_SIZE) - 1)) -#define PIO_BFINS(name,value,old) (((old) & ~(((1 << PIO_##name##_SIZE) - 1) << PIO_##name##_OFFSET)) | PIO_BF(name,value)) - -/* Register access macros */ -#define pio_readl(port,reg) \ - __raw_readl((port)->regs + PIO_##reg) -#define pio_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + PIO_##reg) - -void at32_init_pio(struct platform_device *pdev); - -#endif /* __ARCH_AVR32_AT32AP_PIO_H__ */ diff --git a/arch/avr32/mach-at32ap/pm-at32ap700x.S b/arch/avr32/mach-at32ap/pm-at32ap700x.S deleted file mode 100644 index 1c8e4e6bff03..000000000000 --- a/arch/avr32/mach-at32ap/pm-at32ap700x.S +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Low-level Power Management code. - * - * Copyright (C) 2008 Atmel Corporation - * - * 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 <asm/asm.h> -#include <asm/asm-offsets.h> -#include <asm/thread_info.h> -#include <mach/pm.h> - -#include "pm.h" -#include "sdramc.h" - -/* Same as 0xfff00000 but fits in a 21 bit signed immediate */ -#define PM_BASE -0x100000 - - /* Keep this close to the irq handlers */ - .section .irq.text, "ax", @progbits - - /* - * void cpu_enter_idle(void) - * - * Put the CPU into "idle" mode, in which it will consume - * significantly less power. - * - * If an interrupt comes along in the window between - * unmask_interrupts and the sleep instruction below, the - * interrupt code will adjust the return address so that we - * never execute the sleep instruction. This is required - * because the AP7000 doesn't unmask interrupts when entering - * sleep modes; later CPUs may not need this workaround. - */ - .global cpu_enter_idle - .type cpu_enter_idle, @function -cpu_enter_idle: - mask_interrupts - get_thread_info r8 - ld.w r9, r8[TI_flags] - bld r9, TIF_NEED_RESCHED - brcs .Lret_from_sleep - sbr r9, TIF_CPU_GOING_TO_SLEEP - st.w r8[TI_flags], r9 - unmask_interrupts - sleep CPU_SLEEP_IDLE - .size cpu_enter_idle, . - cpu_enter_idle - - /* - * Common return path for PM functions that don't run from - * SRAM. - */ - .global cpu_idle_skip_sleep - .type cpu_idle_skip_sleep, @function -cpu_idle_skip_sleep: - mask_interrupts - ld.w r9, r8[TI_flags] - cbr r9, TIF_CPU_GOING_TO_SLEEP - st.w r8[TI_flags], r9 -.Lret_from_sleep: - unmask_interrupts - retal r12 - .size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep - -#ifdef CONFIG_PM - .section .init.text, "ax", @progbits - - .global pm_exception - .type pm_exception, @function -pm_exception: - /* - * Exceptions are masked when we switch to this handler, so - * we'll only get "unrecoverable" exceptions (offset 0.) - */ - sub r12, pc, . - .Lpanic_msg - lddpc pc, .Lpanic_addr - - .align 2 -.Lpanic_addr: - .long panic -.Lpanic_msg: - .asciz "Unrecoverable exception during suspend\n" - .size pm_exception, . - pm_exception - - .global pm_irq0 - .type pm_irq0, @function -pm_irq0: - /* Disable interrupts and return after the sleep instruction */ - mfsr r9, SYSREG_RSR_INT0 - mtsr SYSREG_RAR_INT0, r8 - sbr r9, SYSREG_GM_OFFSET - mtsr SYSREG_RSR_INT0, r9 - rete - - /* - * void cpu_enter_standby(unsigned long sdramc_base) - * - * Enter PM_SUSPEND_STANDBY mode. At this point, all drivers - * are suspended and interrupts are disabled. Interrupts - * marked as 'wakeup' event sources may still come along and - * get us out of here. - * - * The SDRAM will be put into self-refresh mode (which does - * not require a clock from the CPU), and the CPU will be put - * into "frozen" mode (HSB bus stopped). The SDRAM controller - * will automatically bring the SDRAM into normal mode on the - * first access, and the power manager will automatically - * start the HSB and CPU clocks upon a wakeup event. - * - * This code uses the same "skip sleep" technique as above. - * It is very important that we jump directly to - * cpu_after_sleep after the sleep instruction since that's - * where we'll end up if the interrupt handler decides that we - * need to skip the sleep instruction. - */ - .global pm_standby - .type pm_standby, @function -pm_standby: - /* - * interrupts are already masked at this point, and EVBA - * points to pm_exception above. - */ - ld.w r10, r12[SDRAMC_LPR] - sub r8, pc, . - 1f /* return address for irq handler */ - mov r11, SDRAMC_LPR_LPCB_SELF_RFR - bfins r10, r11, 0, 2 /* LPCB <- self Refresh */ - sync 0 /* flush write buffer */ - st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ - ld.w r11, r12[SDRAMC_LPR] - unmask_interrupts - sleep CPU_SLEEP_FROZEN -1: mask_interrupts - retal r12 - .size pm_standby, . - pm_standby - - .global pm_suspend_to_ram - .type pm_suspend_to_ram, @function -pm_suspend_to_ram: - /* - * interrupts are already masked at this point, and EVBA - * points to pm_exception above. - */ - mov r11, 0 - cache r11[2], 8 /* clean all dcache lines */ - sync 0 /* flush write buffer */ - ld.w r10, r12[SDRAMC_LPR] - sub r8, pc, . - 1f /* return address for irq handler */ - mov r11, SDRAMC_LPR_LPCB_SELF_RFR - bfins r10, r11, 0, 2 /* LPCB <- self refresh */ - st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ - ld.w r11, r12[SDRAMC_LPR] - - unmask_interrupts - sleep CPU_SLEEP_STOP -1: mask_interrupts - - retal r12 - .size pm_suspend_to_ram, . - pm_suspend_to_ram - - .global pm_sram_end - .type pm_sram_end, @function -pm_sram_end: - .size pm_sram_end, 0 - -#endif /* CONFIG_PM */ diff --git a/arch/avr32/mach-at32ap/pm.c b/arch/avr32/mach-at32ap/pm.c deleted file mode 100644 index db190842b80c..000000000000 --- a/arch/avr32/mach-at32ap/pm.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * AVR32 AP Power Management - * - * Copyright (C) 2008 Atmel Corporation - * - * 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/io.h> -#include <linux/suspend.h> -#include <linux/vmalloc.h> - -#include <asm/cacheflush.h> -#include <asm/sysreg.h> - -#include <mach/chip.h> -#include <mach/pm.h> -#include <mach/sram.h> - -#include "sdramc.h" - -#define SRAM_PAGE_FLAGS (SYSREG_BIT(TLBELO_D) | SYSREG_BF(SZ, 1) \ - | SYSREG_BF(AP, 3) | SYSREG_BIT(G)) - - -static unsigned long pm_sram_start; -static size_t pm_sram_size; -static struct vm_struct *pm_sram_area; - -static void (*avr32_pm_enter_standby)(unsigned long sdramc_base); -static void (*avr32_pm_enter_str)(unsigned long sdramc_base); - -/* - * Must be called with interrupts disabled. Exceptions will be masked - * on return (i.e. all exceptions will be "unrecoverable".) - */ -static void *avr32_pm_map_sram(void) -{ - unsigned long vaddr; - unsigned long page_addr; - u32 tlbehi; - u32 mmucr; - - vaddr = (unsigned long)pm_sram_area->addr; - page_addr = pm_sram_start & PAGE_MASK; - - /* - * Mask exceptions and grab the first TLB entry. We won't be - * needing it while sleeping. - */ - asm volatile("ssrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory"); - - mmucr = sysreg_read(MMUCR); - tlbehi = sysreg_read(TLBEHI); - sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr)); - - tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); - tlbehi |= vaddr & PAGE_MASK; - tlbehi |= SYSREG_BIT(TLBEHI_V); - - sysreg_write(TLBELO, page_addr | SRAM_PAGE_FLAGS); - sysreg_write(TLBEHI, tlbehi); - __builtin_tlbw(); - - return (void *)(vaddr + pm_sram_start - page_addr); -} - -/* - * Must be called with interrupts disabled. Exceptions will be - * unmasked on return. - */ -static void avr32_pm_unmap_sram(void) -{ - u32 mmucr; - u32 tlbehi; - u32 tlbarlo; - - /* Going to update TLB entry at index 0 */ - mmucr = sysreg_read(MMUCR); - tlbehi = sysreg_read(TLBEHI); - sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr)); - - /* Clear the "valid" bit */ - tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); - sysreg_write(TLBEHI, tlbehi); - - /* Mark it as "not accessed" */ - tlbarlo = sysreg_read(TLBARLO); - sysreg_write(TLBARLO, tlbarlo | 0x80000000U); - - /* Update the TLB */ - __builtin_tlbw(); - - /* Unmask exceptions */ - asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory"); -} - -static int avr32_pm_valid_state(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_ON: - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - return 1; - - default: - return 0; - } -} - -static int avr32_pm_enter(suspend_state_t state) -{ - u32 lpr_saved; - u32 evba_saved; - void *sram; - - switch (state) { - case PM_SUSPEND_STANDBY: - sram = avr32_pm_map_sram(); - - /* Switch to in-sram exception handlers */ - evba_saved = sysreg_read(EVBA); - sysreg_write(EVBA, (unsigned long)sram); - - /* - * Save the LPR register so that we can re-enable - * SDRAM Low Power mode on resume. - */ - lpr_saved = sdramc_readl(LPR); - pr_debug("%s: Entering standby...\n", __func__); - avr32_pm_enter_standby(SDRAMC_BASE); - sdramc_writel(LPR, lpr_saved); - - /* Switch back to regular exception handlers */ - sysreg_write(EVBA, evba_saved); - - avr32_pm_unmap_sram(); - break; - - case PM_SUSPEND_MEM: - sram = avr32_pm_map_sram(); - - /* Switch to in-sram exception handlers */ - evba_saved = sysreg_read(EVBA); - sysreg_write(EVBA, (unsigned long)sram); - - /* - * Save the LPR register so that we can re-enable - * SDRAM Low Power mode on resume. - */ - lpr_saved = sdramc_readl(LPR); - pr_debug("%s: Entering suspend-to-ram...\n", __func__); - avr32_pm_enter_str(SDRAMC_BASE); - sdramc_writel(LPR, lpr_saved); - - /* Switch back to regular exception handlers */ - sysreg_write(EVBA, evba_saved); - - avr32_pm_unmap_sram(); - break; - - case PM_SUSPEND_ON: - pr_debug("%s: Entering idle...\n", __func__); - cpu_enter_idle(); - break; - - default: - pr_debug("%s: Invalid suspend state %d\n", __func__, state); - goto out; - } - - pr_debug("%s: wakeup\n", __func__); - -out: - return 0; -} - -static const struct platform_suspend_ops avr32_pm_ops = { - .valid = avr32_pm_valid_state, - .enter = avr32_pm_enter, -}; - -static unsigned long __init avr32_pm_offset(void *symbol) -{ - extern u8 pm_exception[]; - - return (unsigned long)symbol - (unsigned long)pm_exception; -} - -static int __init avr32_pm_init(void) -{ - extern u8 pm_exception[]; - extern u8 pm_irq0[]; - extern u8 pm_standby[]; - extern u8 pm_suspend_to_ram[]; - extern u8 pm_sram_end[]; - void *dst; - - /* - * To keep things simple, we depend on not needing more than a - * single page. - */ - pm_sram_size = avr32_pm_offset(pm_sram_end); - if (pm_sram_size > PAGE_SIZE) - goto err; - - pm_sram_start = sram_alloc(pm_sram_size); - if (!pm_sram_start) - goto err_alloc_sram; - - /* Grab a virtual area we can use later on. */ - pm_sram_area = get_vm_area(pm_sram_size, VM_IOREMAP); - if (!pm_sram_area) - goto err_vm_area; - pm_sram_area->phys_addr = pm_sram_start; - - local_irq_disable(); - dst = avr32_pm_map_sram(); - memcpy(dst, pm_exception, pm_sram_size); - flush_dcache_region(dst, pm_sram_size); - invalidate_icache_region(dst, pm_sram_size); - avr32_pm_unmap_sram(); - local_irq_enable(); - - avr32_pm_enter_standby = dst + avr32_pm_offset(pm_standby); - avr32_pm_enter_str = dst + avr32_pm_offset(pm_suspend_to_ram); - intc_set_suspend_handler(avr32_pm_offset(pm_irq0)); - - suspend_set_ops(&avr32_pm_ops); - - printk("AVR32 AP Power Management enabled\n"); - - return 0; - -err_vm_area: - sram_free(pm_sram_start, pm_sram_size); -err_alloc_sram: -err: - pr_err("AVR32 Power Management initialization failed\n"); - return -ENOMEM; -} -arch_initcall(avr32_pm_init); diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h deleted file mode 100644 index 532a3732c214..000000000000 --- a/arch/avr32/mach-at32ap/pm.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Register definitions for the Power Manager (PM) - */ -#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__ -#define __ARCH_AVR32_MACH_AT32AP_PM_H__ - -/* PM register offsets */ -#define PM_MCCTRL 0x0000 -#define PM_CKSEL 0x0004 -#define PM_CPU_MASK 0x0008 -#define PM_HSB_MASK 0x000c -#define PM_PBA_MASK 0x0010 -#define PM_PBB_MASK 0x0014 -#define PM_PLL0 0x0020 -#define PM_PLL1 0x0024 -#define PM_IER 0x0040 -#define PM_IDR 0x0044 -#define PM_IMR 0x0048 -#define PM_ISR 0x004c -#define PM_ICR 0x0050 -#define PM_GCCTRL(x) (0x0060 + 4 * (x)) -#define PM_RCAUSE 0x00c0 - -/* Bitfields in CKSEL */ -#define PM_CPUSEL_OFFSET 0 -#define PM_CPUSEL_SIZE 3 -#define PM_CPUDIV_OFFSET 7 -#define PM_CPUDIV_SIZE 1 -#define PM_HSBSEL_OFFSET 8 -#define PM_HSBSEL_SIZE 3 -#define PM_HSBDIV_OFFSET 15 -#define PM_HSBDIV_SIZE 1 -#define PM_PBASEL_OFFSET 16 -#define PM_PBASEL_SIZE 3 -#define PM_PBADIV_OFFSET 23 -#define PM_PBADIV_SIZE 1 -#define PM_PBBSEL_OFFSET 24 -#define PM_PBBSEL_SIZE 3 -#define PM_PBBDIV_OFFSET 31 -#define PM_PBBDIV_SIZE 1 - -/* Bitfields in PLL0 */ -#define PM_PLLEN_OFFSET 0 -#define PM_PLLEN_SIZE 1 -#define PM_PLLOSC_OFFSET 1 -#define PM_PLLOSC_SIZE 1 -#define PM_PLLOPT_OFFSET 2 -#define PM_PLLOPT_SIZE 3 -#define PM_PLLDIV_OFFSET 8 -#define PM_PLLDIV_SIZE 8 -#define PM_PLLMUL_OFFSET 16 -#define PM_PLLMUL_SIZE 8 -#define PM_PLLCOUNT_OFFSET 24 -#define PM_PLLCOUNT_SIZE 6 -#define PM_PLLTEST_OFFSET 31 -#define PM_PLLTEST_SIZE 1 - -/* Bitfields in ICR */ -#define PM_LOCK0_OFFSET 0 -#define PM_LOCK0_SIZE 1 -#define PM_LOCK1_OFFSET 1 -#define PM_LOCK1_SIZE 1 -#define PM_WAKE_OFFSET 2 -#define PM_WAKE_SIZE 1 -#define PM_CKRDY_OFFSET 5 -#define PM_CKRDY_SIZE 1 -#define PM_MSKRDY_OFFSET 6 -#define PM_MSKRDY_SIZE 1 - -/* Bitfields in GCCTRL0 */ -#define PM_OSCSEL_OFFSET 0 -#define PM_OSCSEL_SIZE 1 -#define PM_PLLSEL_OFFSET 1 -#define PM_PLLSEL_SIZE 1 -#define PM_CEN_OFFSET 2 -#define PM_CEN_SIZE 1 -#define PM_DIVEN_OFFSET 4 -#define PM_DIVEN_SIZE 1 -#define PM_DIV_OFFSET 8 -#define PM_DIV_SIZE 8 - -/* Bitfields in RCAUSE */ -#define PM_POR_OFFSET 0 -#define PM_POR_SIZE 1 -#define PM_EXT_OFFSET 2 -#define PM_EXT_SIZE 1 -#define PM_WDT_OFFSET 3 -#define PM_WDT_SIZE 1 -#define PM_NTAE_OFFSET 4 -#define PM_NTAE_SIZE 1 - -/* Bit manipulation macros */ -#define PM_BIT(name) \ - (1 << PM_##name##_OFFSET) -#define PM_BF(name,value) \ - (((value) & ((1 << PM_##name##_SIZE) - 1)) \ - << PM_##name##_OFFSET) -#define PM_BFEXT(name,value) \ - (((value) >> PM_##name##_OFFSET) \ - & ((1 << PM_##name##_SIZE) - 1)) -#define PM_BFINS(name,value,old)\ - (((old) & ~(((1 << PM_##name##_SIZE) - 1) \ - << PM_##name##_OFFSET)) \ - | PM_BF(name,value)) - -/* Register access macros */ -#define pm_readl(reg) \ - __raw_readl((void __iomem __force *)PM_BASE + PM_##reg) -#define pm_writel(reg,value) \ - __raw_writel((value), (void __iomem __force *)PM_BASE + PM_##reg) - -#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */ diff --git a/arch/avr32/mach-at32ap/sdramc.h b/arch/avr32/mach-at32ap/sdramc.h deleted file mode 100644 index 66eeaed49073..000000000000 --- a/arch/avr32/mach-at32ap/sdramc.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Register definitions for the AT32AP SDRAM Controller - * - * Copyright (C) 2008 Atmel Corporation - * - * 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. - */ - -/* Register offsets */ -#define SDRAMC_MR 0x0000 -#define SDRAMC_TR 0x0004 -#define SDRAMC_CR 0x0008 -#define SDRAMC_HSR 0x000c -#define SDRAMC_LPR 0x0010 -#define SDRAMC_IER 0x0014 -#define SDRAMC_IDR 0x0018 -#define SDRAMC_IMR 0x001c -#define SDRAMC_ISR 0x0020 -#define SDRAMC_MDR 0x0024 - -/* MR - Mode Register */ -#define SDRAMC_MR_MODE_NORMAL ( 0 << 0) -#define SDRAMC_MR_MODE_NOP ( 1 << 0) -#define SDRAMC_MR_MODE_BANKS_PRECHARGE ( 2 << 0) -#define SDRAMC_MR_MODE_LOAD_MODE ( 3 << 0) -#define SDRAMC_MR_MODE_AUTO_REFRESH ( 4 << 0) -#define SDRAMC_MR_MODE_EXT_LOAD_MODE ( 5 << 0) -#define SDRAMC_MR_MODE_POWER_DOWN ( 6 << 0) - -/* CR - Configuration Register */ -#define SDRAMC_CR_NC_8_BITS ( 0 << 0) -#define SDRAMC_CR_NC_9_BITS ( 1 << 0) -#define SDRAMC_CR_NC_10_BITS ( 2 << 0) -#define SDRAMC_CR_NC_11_BITS ( 3 << 0) -#define SDRAMC_CR_NR_11_BITS ( 0 << 2) -#define SDRAMC_CR_NR_12_BITS ( 1 << 2) -#define SDRAMC_CR_NR_13_BITS ( 2 << 2) -#define SDRAMC_CR_NB_2_BANKS ( 0 << 4) -#define SDRAMC_CR_NB_4_BANKS ( 1 << 4) -#define SDRAMC_CR_CAS(x) ((x) << 5) -#define SDRAMC_CR_DBW_32_BITS ( 0 << 7) -#define SDRAMC_CR_DBW_16_BITS ( 1 << 7) -#define SDRAMC_CR_TWR(x) ((x) << 8) -#define SDRAMC_CR_TRC(x) ((x) << 12) -#define SDRAMC_CR_TRP(x) ((x) << 16) -#define SDRAMC_CR_TRCD(x) ((x) << 20) -#define SDRAMC_CR_TRAS(x) ((x) << 24) -#define SDRAMC_CR_TXSR(x) ((x) << 28) - -/* HSR - High Speed Register */ -#define SDRAMC_HSR_DA ( 1 << 0) - -/* LPR - Low Power Register */ -#define SDRAMC_LPR_LPCB_INHIBIT ( 0 << 0) -#define SDRAMC_LPR_LPCB_SELF_RFR ( 1 << 0) -#define SDRAMC_LPR_LPCB_PDOWN ( 2 << 0) -#define SDRAMC_LPR_LPCB_DEEP_PDOWN ( 3 << 0) -#define SDRAMC_LPR_PASR(x) ((x) << 4) -#define SDRAMC_LPR_TCSR(x) ((x) << 8) -#define SDRAMC_LPR_DS(x) ((x) << 10) -#define SDRAMC_LPR_TIMEOUT(x) ((x) << 12) - -/* IER/IDR/IMR/ISR - Interrupt Enable/Disable/Mask/Status Register */ -#define SDRAMC_ISR_RES ( 1 << 0) - -/* MDR - Memory Device Register */ -#define SDRAMC_MDR_MD_SDRAM ( 0 << 0) -#define SDRAMC_MDR_MD_LOW_PWR_SDRAM ( 1 << 0) - -/* Register access macros */ -#define sdramc_readl(reg) \ - __raw_readl((void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg) -#define sdramc_writel(reg, value) \ - __raw_writel(value, (void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg) diff --git a/arch/avr32/mm/Makefile b/arch/avr32/mm/Makefile deleted file mode 100644 index 0066491f90d4..000000000000 --- a/arch/avr32/mm/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the Linux/AVR32 kernel. -# - -obj-y += init.o clear_page.o copy_page.o dma-coherent.o -obj-y += ioremap.o cache.o fault.o tlb.o diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c deleted file mode 100644 index d9476825fc43..000000000000 --- a/arch/avr32/mm/cache.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/highmem.h> -#include <linux/unistd.h> - -#include <asm/cacheflush.h> -#include <asm/cachectl.h> -#include <asm/processor.h> -#include <linux/uaccess.h> -#include <asm/syscalls.h> - -/* - * If you attempt to flush anything more than this, you need superuser - * privileges. The value is completely arbitrary. - */ -#define CACHEFLUSH_MAX_LEN 1024 - -void invalidate_dcache_region(void *start, size_t size) -{ - unsigned long v, begin, end, linesz, mask; - - linesz = boot_cpu_data.dcache.linesz; - mask = linesz - 1; - - /* when first and/or last cachelines are shared, flush them - * instead of invalidating ... never discard valid data! - */ - begin = (unsigned long)start; - end = begin + size; - - if (begin & mask) { - flush_dcache_line(start); - begin += linesz; - } - if (end & mask) { - flush_dcache_line((void *)end); - end &= ~mask; - } - - /* remaining cachelines only need invalidation */ - for (v = begin; v < end; v += linesz) - invalidate_dcache_line((void *)v); - flush_write_buffer(); -} - -void clean_dcache_region(void *start, size_t size) -{ - unsigned long v, begin, end, linesz; - - linesz = boot_cpu_data.dcache.linesz; - begin = (unsigned long)start & ~(linesz - 1); - end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); - - for (v = begin; v < end; v += linesz) - clean_dcache_line((void *)v); - flush_write_buffer(); -} - -void flush_dcache_region(void *start, size_t size) -{ - unsigned long v, begin, end, linesz; - - linesz = boot_cpu_data.dcache.linesz; - begin = (unsigned long)start & ~(linesz - 1); - end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); - - for (v = begin; v < end; v += linesz) - flush_dcache_line((void *)v); - flush_write_buffer(); -} - -void invalidate_icache_region(void *start, size_t size) -{ - unsigned long v, begin, end, linesz; - - linesz = boot_cpu_data.icache.linesz; - begin = (unsigned long)start & ~(linesz - 1); - end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); - - for (v = begin; v < end; v += linesz) - invalidate_icache_line((void *)v); -} - -static inline void __flush_icache_range(unsigned long start, unsigned long end) -{ - unsigned long v, linesz; - - linesz = boot_cpu_data.dcache.linesz; - for (v = start; v < end; v += linesz) { - clean_dcache_line((void *)v); - invalidate_icache_line((void *)v); - } - - flush_write_buffer(); -} - -/* - * This one is called after a module has been loaded. - */ -void flush_icache_range(unsigned long start, unsigned long end) -{ - unsigned long linesz; - - linesz = boot_cpu_data.dcache.linesz; - __flush_icache_range(start & ~(linesz - 1), - (end + linesz - 1) & ~(linesz - 1)); -} -EXPORT_SYMBOL(flush_icache_range); - -/* - * This one is called from __do_fault() and do_swap_page(). - */ -void flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - if (vma->vm_flags & VM_EXEC) { - void *v = page_address(page); - __flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE); - } -} - -asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) -{ - int ret; - - if (len > CACHEFLUSH_MAX_LEN) { - ret = -EPERM; - if (!capable(CAP_SYS_ADMIN)) - goto out; - } - - ret = -EFAULT; - if (!access_ok(VERIFY_WRITE, addr, len)) - goto out; - - switch (operation) { - case CACHE_IFLUSH: - flush_icache_range((unsigned long)addr, - (unsigned long)addr + len); - ret = 0; - break; - default: - ret = -EINVAL; - } - -out: - return ret; -} - -void copy_to_user_page(struct vm_area_struct *vma, struct page *page, - unsigned long vaddr, void *dst, const void *src, - unsigned long len) -{ - memcpy(dst, src, len); - if (vma->vm_flags & VM_EXEC) - flush_icache_range((unsigned long)dst, - (unsigned long)dst + len); -} diff --git a/arch/avr32/mm/clear_page.S b/arch/avr32/mm/clear_page.S deleted file mode 100644 index 5d70dca00699..000000000000 --- a/arch/avr32/mm/clear_page.S +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/page.h> - -/* - * clear_page - * r12: P1 address (to) - */ - .text - .global clear_page -clear_page: - sub r9, r12, -PAGE_SIZE - mov r10, 0 - mov r11, 0 -0: st.d r12++, r10 - cp r12, r9 - brne 0b - mov pc, lr diff --git a/arch/avr32/mm/copy_page.S b/arch/avr32/mm/copy_page.S deleted file mode 100644 index c2b3752946b8..000000000000 --- a/arch/avr32/mm/copy_page.S +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/page.h> - -/* - * copy_page - * - * r12 to (P1 address) - * r11 from (P1 address) - * r8-r10 scratch - */ - .text - .global copy_page -copy_page: - sub r10, r11, -(1 << PAGE_SHIFT) - /* pref r11[0] */ -1: /* pref r11[8] */ - ld.d r8, r11++ - st.d r12++, r8 - cp r11, r10 - brlo 1b - mov pc, lr diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c deleted file mode 100644 index 555222d4f414..000000000000 --- a/arch/avr32/mm/dma-coherent.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/dma-mapping.h> -#include <linux/gfp.h> -#include <linux/export.h> -#include <linux/mm.h> -#include <linux/device.h> -#include <linux/scatterlist.h> - -#include <asm/processor.h> -#include <asm/cacheflush.h> -#include <asm/io.h> -#include <asm/addrspace.h> - -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction) -{ - /* - * No need to sync an uncached area - */ - if (PXSEG(vaddr) == P2SEG) - return; - - switch (direction) { - case DMA_FROM_DEVICE: /* invalidate only */ - invalidate_dcache_region(vaddr, size); - break; - case DMA_TO_DEVICE: /* writeback only */ - clean_dcache_region(vaddr, size); - break; - case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - flush_dcache_region(vaddr, size); - break; - default: - BUG(); - } -} -EXPORT_SYMBOL(dma_cache_sync); - -static struct page *__dma_alloc(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t gfp) -{ - struct page *page, *free, *end; - int order; - - /* Following is a work-around (a.k.a. hack) to prevent pages - * with __GFP_COMP being passed to split_page() which cannot - * handle them. The real problem is that this flag probably - * should be 0 on AVR32 as it is not supported on this - * platform--see CONFIG_HUGETLB_PAGE. */ - gfp &= ~(__GFP_COMP); - - size = PAGE_ALIGN(size); - order = get_order(size); - - page = alloc_pages(gfp, order); - if (!page) - return NULL; - split_page(page, order); - - /* - * When accessing physical memory with valid cache data, we - * get a cache hit even if the virtual memory region is marked - * as uncached. - * - * Since the memory is newly allocated, there is no point in - * doing a writeback. If the previous owner cares, he should - * have flushed the cache before releasing the memory. - */ - invalidate_dcache_region(phys_to_virt(page_to_phys(page)), size); - - *handle = page_to_bus(page); - free = page + (size >> PAGE_SHIFT); - end = page + (1 << order); - - /* - * Free any unused pages - */ - while (free < end) { - __free_page(free); - free++; - } - - return page; -} - -static void __dma_free(struct device *dev, size_t size, - struct page *page, dma_addr_t handle) -{ - struct page *end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT); - - while (page < end) - __free_page(page++); -} - -static void *avr32_dma_alloc(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t gfp, unsigned long attrs) -{ - struct page *page; - dma_addr_t phys; - - page = __dma_alloc(dev, size, handle, gfp); - if (!page) - return NULL; - phys = page_to_phys(page); - - if (attrs & DMA_ATTR_WRITE_COMBINE) { - /* Now, map the page into P3 with write-combining turned on */ - *handle = phys; - return __ioremap(phys, size, _PAGE_BUFFER); - } else { - return phys_to_uncached(phys); - } -} - -static void avr32_dma_free(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t handle, unsigned long attrs) -{ - struct page *page; - - if (attrs & DMA_ATTR_WRITE_COMBINE) { - iounmap(cpu_addr); - - page = phys_to_page(handle); - } else { - void *addr = phys_to_cached(uncached_to_phys(cpu_addr)); - - pr_debug("avr32_dma_free addr %p (phys %08lx) size %u\n", - cpu_addr, (unsigned long)handle, (unsigned)size); - - BUG_ON(!virt_addr_valid(addr)); - page = virt_to_page(addr); - } - - __dma_free(dev, size, page, handle); -} - -static dma_addr_t avr32_dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction, unsigned long attrs) -{ - void *cpu_addr = page_address(page) + offset; - - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - dma_cache_sync(dev, cpu_addr, size, direction); - return virt_to_bus(cpu_addr); -} - -static int avr32_dma_map_sg(struct device *dev, struct scatterlist *sglist, - int nents, enum dma_data_direction direction, - unsigned long attrs) -{ - int i; - struct scatterlist *sg; - - for_each_sg(sglist, sg, nents, i) { - char *virt; - - sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset; - virt = sg_virt(sg); - - if (attrs & DMA_ATTR_SKIP_CPU_SYNC) - continue; - - dma_cache_sync(dev, virt, sg->length, direction); - } - - return nents; -} - -static void avr32_dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction direction) -{ - dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); -} - -static void avr32_dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sglist, int nents, - enum dma_data_direction direction) -{ - int i; - struct scatterlist *sg; - - for_each_sg(sglist, sg, nents, i) - dma_cache_sync(dev, sg_virt(sg), sg->length, direction); -} - -const struct dma_map_ops avr32_dma_ops = { - .alloc = avr32_dma_alloc, - .free = avr32_dma_free, - .map_page = avr32_dma_map_page, - .map_sg = avr32_dma_map_sg, - .sync_single_for_device = avr32_dma_sync_single_for_device, - .sync_sg_for_device = avr32_dma_sync_sg_for_device, -}; -EXPORT_SYMBOL(avr32_dma_ops); diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c deleted file mode 100644 index b3977e9208a3..000000000000 --- a/arch/avr32/mm/fault.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * Based on linux/arch/sh/mm/fault.c: - * Copyright (C) 1999 Niibe Yutaka - * - * 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/mm.h> -#include <linux/extable.h> -#include <linux/pagemap.h> -#include <linux/kdebug.h> -#include <linux/kprobes.h> -#include <linux/uaccess.h> - -#include <asm/mmu_context.h> -#include <asm/sysreg.h> -#include <asm/tlb.h> - -#ifdef CONFIG_KPROBES -static inline int notify_page_fault(struct pt_regs *regs, int trap) -{ - int ret = 0; - - if (!user_mode(regs)) { - if (kprobe_running() && kprobe_fault_handler(regs, trap)) - ret = 1; - } - - return ret; -} -#else -static inline int notify_page_fault(struct pt_regs *regs, int trap) -{ - return 0; -} -#endif - -int exception_trace = 1; - -/* - * This routine handles page faults. It determines the address and the - * problem, and then passes it off to one of the appropriate routines. - * - * ecr is the Exception Cause Register. Possible values are: - * 6: Protection fault (instruction access) - * 15: Protection fault (read access) - * 16: Protection fault (write access) - * 20: Page not found (instruction access) - * 24: Page not found (read access) - * 28: Page not found (write access) - */ -asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) -{ - struct task_struct *tsk; - struct mm_struct *mm; - struct vm_area_struct *vma; - const struct exception_table_entry *fixup; - unsigned long address; - unsigned long page; - long signr; - int code; - int fault; - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; - - if (notify_page_fault(regs, ecr)) - return; - - address = sysreg_read(TLBEAR); - - tsk = current; - mm = tsk->mm; - - signr = SIGSEGV; - code = SEGV_MAPERR; - - /* - * If we're in an interrupt or have no user context, we must - * not take the fault... - */ - if (faulthandler_disabled() || !mm || regs->sr & SYSREG_BIT(GM)) - goto no_context; - - local_irq_enable(); - - if (user_mode(regs)) - flags |= FAULT_FLAG_USER; -retry: - down_read(&mm->mmap_sem); - - vma = find_vma(mm, address); - if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; - - /* - * Ok, we have a good vm_area for this memory access, so we - * can handle it... - */ -good_area: - code = SEGV_ACCERR; - - switch (ecr) { - case ECR_PROTECTION_X: - case ECR_TLB_MISS_X: - if (!(vma->vm_flags & VM_EXEC)) - goto bad_area; - break; - case ECR_PROTECTION_R: - case ECR_TLB_MISS_R: - if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) - goto bad_area; - break; - case ECR_PROTECTION_W: - case ECR_TLB_MISS_W: - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - flags |= FAULT_FLAG_WRITE; - break; - default: - panic("Unhandled case %lu in do_page_fault!", ecr); - } - - /* - * If for any reason at all we couldn't handle the fault, make - * sure we exit gracefully rather than endlessly redo the - * fault. - */ - fault = handle_mm_fault(vma, address, flags); - - if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) - return; - - if (unlikely(fault & VM_FAULT_ERROR)) { - if (fault & VM_FAULT_OOM) - goto out_of_memory; - else if (fault & VM_FAULT_SIGSEGV) - goto bad_area; - else if (fault & VM_FAULT_SIGBUS) - goto do_sigbus; - BUG(); - } - - if (flags & FAULT_FLAG_ALLOW_RETRY) { - if (fault & VM_FAULT_MAJOR) - tsk->maj_flt++; - else - tsk->min_flt++; - if (fault & VM_FAULT_RETRY) { - flags &= ~FAULT_FLAG_ALLOW_RETRY; - flags |= FAULT_FLAG_TRIED; - - /* - * No need to up_read(&mm->mmap_sem) as we would have - * already released it in __lock_page_or_retry() in - * mm/filemap.c. - */ - goto retry; - } - } - - up_read(&mm->mmap_sem); - return; - - /* - * Something tried to access memory that isn't in our memory - * map. Fix it, but check if it's kernel or user first... - */ -bad_area: - up_read(&mm->mmap_sem); - - if (user_mode(regs)) { - if (exception_trace && printk_ratelimit()) - printk("%s%s[%d]: segfault at %08lx pc %08lx " - "sp %08lx ecr %lu\n", - is_global_init(tsk) ? KERN_EMERG : KERN_INFO, - tsk->comm, tsk->pid, address, regs->pc, - regs->sp, ecr); - _exception(SIGSEGV, regs, code, address); - return; - } - -no_context: - /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - - /* - * Oops. The kernel tried to access some bad page. We'll have - * to terminate things with extreme prejudice. - */ - if (address < PAGE_SIZE) - printk(KERN_ALERT - "Unable to handle kernel NULL pointer dereference"); - else - printk(KERN_ALERT - "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n", address); - - page = sysreg_read(PTBR); - printk(KERN_ALERT "ptbr = %08lx", page); - if (address >= TASK_SIZE) - page = (unsigned long)swapper_pg_dir; - if (page) { - page = ((unsigned long *)page)[address >> 22]; - printk(" pgd = %08lx", page); - if (page & _PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT]; - printk(" pte = %08lx", page); - } - } - printk("\n"); - die("Kernel access of bad area", regs, signr); - return; - - /* - * We ran out of memory, or some other thing happened to us - * that made us unable to handle the page fault gracefully. - */ -out_of_memory: - up_read(&mm->mmap_sem); - if (!user_mode(regs)) - goto no_context; - pagefault_out_of_memory(); - return; - -do_sigbus: - up_read(&mm->mmap_sem); - - /* Kernel mode? Handle exceptions or die */ - signr = SIGBUS; - code = BUS_ADRERR; - if (!user_mode(regs)) - goto no_context; - - if (exception_trace) - printk("%s%s[%d]: bus error at %08lx pc %08lx " - "sp %08lx ecr %lu\n", - is_global_init(tsk) ? KERN_EMERG : KERN_INFO, - tsk->comm, tsk->pid, address, regs->pc, - regs->sp, ecr); - - _exception(SIGBUS, regs, BUS_ADRERR, address); -} - -asmlinkage void do_bus_error(unsigned long addr, int write_access, - struct pt_regs *regs) -{ - printk(KERN_ALERT - "Bus error at physical address 0x%08lx (%s access)\n", - addr, write_access ? "write" : "read"); - printk(KERN_INFO "DTLB dump:\n"); - dump_dtlb(); - die("Bus Error", regs, SIGKILL); -} diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c deleted file mode 100644 index def5391d927a..000000000000 --- a/arch/avr32/mm/init.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/kernel.h> -#include <linux/gfp.h> -#include <linux/mm.h> -#include <linux/swap.h> -#include <linux/init.h> -#include <linux/mmzone.h> -#include <linux/module.h> -#include <linux/bootmem.h> -#include <linux/pagemap.h> -#include <linux/nodemask.h> - -#include <asm/page.h> -#include <asm/mmu_context.h> -#include <asm/tlb.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/setup.h> -#include <asm/sections.h> - -pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_data; - -struct page *empty_zero_page; -EXPORT_SYMBOL(empty_zero_page); - -/* - * Cache of MMU context last used. - */ -unsigned long mmu_context_cache = NO_CONTEXT; - -/* - * paging_init() sets up the page tables - * - * This routine also unmaps the page at virtual kernel address 0, so - * that we can trap those pesky NULL-reference errors in the kernel. - */ -void __init paging_init(void) -{ - extern unsigned long _evba; - void *zero_page; - int nid; - - /* - * Make sure we can handle exceptions before enabling - * paging. Not that we should ever _get_ any exceptions this - * early, but you never know... - */ - printk("Exception vectors start at %p\n", &_evba); - sysreg_write(EVBA, (unsigned long)&_evba); - - /* - * Since we are ready to handle exceptions now, we should let - * the CPU generate them... - */ - __asm__ __volatile__ ("csrf %0" : : "i"(SR_EM_BIT)); - - /* - * Allocate the zero page. The allocator will panic if it - * can't satisfy the request, so no need to check. - */ - zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0), - PAGE_SIZE); - - sysreg_write(PTBR, (unsigned long)swapper_pg_dir); - enable_mmu(); - printk ("CPU: Paging enabled\n"); - - for_each_online_node(nid) { - pg_data_t *pgdat = NODE_DATA(nid); - unsigned long zones_size[MAX_NR_ZONES]; - unsigned long low, start_pfn; - - start_pfn = pgdat->bdata->node_min_pfn; - low = pgdat->bdata->node_low_pfn; - - memset(zones_size, 0, sizeof(zones_size)); - zones_size[ZONE_NORMAL] = low - start_pfn; - - printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n", - nid, start_pfn, low); - - free_area_init_node(nid, zones_size, start_pfn, NULL); - - printk("Node %u: mem_map starts at %p\n", - pgdat->node_id, pgdat->node_mem_map); - } - - mem_map = NODE_DATA(0)->node_mem_map; - - empty_zero_page = virt_to_page(zero_page); - flush_dcache_page(empty_zero_page); -} - -void __init mem_init(void) -{ - pg_data_t *pgdat; - - high_memory = NULL; - for_each_online_pgdat(pgdat) - high_memory = max_t(void *, high_memory, - __va(pgdat_end_pfn(pgdat) << PAGE_SHIFT)); - - set_max_mapnr(MAP_NR(high_memory)); - free_all_bootmem(); - mem_init_print_info(NULL); -} - -void free_initmem(void) -{ - free_initmem_default(-1); -} - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - free_reserved_area((void *)start, (void *)end, -1, "initrd"); -} -#endif diff --git a/arch/avr32/mm/ioremap.c b/arch/avr32/mm/ioremap.c deleted file mode 100644 index 7def0d84cec6..000000000000 --- a/arch/avr32/mm/ioremap.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/vmalloc.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/slab.h> - -#include <asm/pgtable.h> -#include <asm/addrspace.h> - -/* - * Re-map an arbitrary physical address space into the kernel virtual - * address space. Needed when the kernel wants to access physical - * memory directly. - */ -void __iomem *__ioremap(unsigned long phys_addr, size_t size, - unsigned long flags) -{ - unsigned long addr; - struct vm_struct *area; - unsigned long offset, last_addr; - pgprot_t prot; - - /* - * Check if we can simply use the P4 segment. This area is - * uncacheable, so if caching/buffering is requested, we can't - * use it. - */ - if ((phys_addr >= P4SEG) && (flags == 0)) - return (void __iomem *)phys_addr; - - /* Don't allow wraparound or zero size */ - last_addr = phys_addr + size - 1; - if (!size || last_addr < phys_addr) - return NULL; - - /* - * XXX: When mapping regular RAM, we'd better make damn sure - * it's never used for anything else. But this is really the - * caller's responsibility... - */ - if (PHYSADDR(P2SEGADDR(phys_addr)) == phys_addr) - return (void __iomem *)P2SEGADDR(phys_addr); - - /* Mappings have to be page-aligned */ - offset = phys_addr & ~PAGE_MASK; - phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr + 1) - phys_addr; - - prot = __pgprot(_PAGE_PRESENT | _PAGE_GLOBAL | _PAGE_RW | _PAGE_DIRTY - | _PAGE_ACCESSED | _PAGE_TYPE_SMALL | flags); - - /* - * Ok, go for it.. - */ - area = get_vm_area(size, VM_IOREMAP); - if (!area) - return NULL; - area->phys_addr = phys_addr; - addr = (unsigned long )area->addr; - if (ioremap_page_range(addr, addr + size, phys_addr, prot)) { - vunmap((void *)addr); - return NULL; - } - - return (void __iomem *)(offset + (char *)addr); -} -EXPORT_SYMBOL(__ioremap); - -void __iounmap(void __iomem *addr) -{ - struct vm_struct *p; - - if ((unsigned long)addr >= P4SEG) - return; - if (PXSEG(addr) == P2SEG) - return; - - p = remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr)); - if (unlikely(!p)) { - printk (KERN_ERR "iounmap: bad address %p\n", addr); - return; - } - - kfree (p); -} -EXPORT_SYMBOL(__iounmap); diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c deleted file mode 100644 index 0da23109f817..000000000000 --- a/arch/avr32/mm/tlb.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * AVR32 TLB operations - * - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/mm.h> - -#include <asm/mmu_context.h> - -/* TODO: Get the correct number from the CONFIG1 system register */ -#define NR_TLB_ENTRIES 32 - -static void show_dtlb_entry(unsigned int index) -{ - u32 tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save; - unsigned long flags; - - local_irq_save(flags); - mmucr_save = sysreg_read(MMUCR); - tlbehi_save = sysreg_read(TLBEHI); - mmucr = SYSREG_BFINS(DRP, index, mmucr_save); - sysreg_write(MMUCR, mmucr); - - __builtin_tlbr(); - cpu_sync_pipeline(); - - tlbehi = sysreg_read(TLBEHI); - tlbelo = sysreg_read(TLBELO); - - printk("%2u: %c %c %02x %05x %05x %o %o %c %c %c %c\n", - index, - SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0', - SYSREG_BFEXT(G, tlbelo) ? '1' : '0', - SYSREG_BFEXT(ASID, tlbehi), - SYSREG_BFEXT(VPN, tlbehi) >> 2, - SYSREG_BFEXT(PFN, tlbelo) >> 2, - SYSREG_BFEXT(AP, tlbelo), - SYSREG_BFEXT(SZ, tlbelo), - SYSREG_BFEXT(TLBELO_C, tlbelo) ? 'C' : ' ', - SYSREG_BFEXT(B, tlbelo) ? 'B' : ' ', - SYSREG_BFEXT(W, tlbelo) ? 'W' : ' ', - SYSREG_BFEXT(TLBELO_D, tlbelo) ? 'D' : ' '); - - sysreg_write(MMUCR, mmucr_save); - sysreg_write(TLBEHI, tlbehi_save); - cpu_sync_pipeline(); - local_irq_restore(flags); -} - -void dump_dtlb(void) -{ - unsigned int i; - - printk("ID V G ASID VPN PFN AP SZ C B W D\n"); - for (i = 0; i < NR_TLB_ENTRIES; i++) - show_dtlb_entry(i); -} - -static void update_dtlb(unsigned long address, pte_t pte) -{ - u32 tlbehi; - u32 mmucr; - - /* - * We're not changing the ASID here, so no need to flush the - * pipeline. - */ - tlbehi = sysreg_read(TLBEHI); - tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); - tlbehi |= address & MMU_VPN_MASK; - tlbehi |= SYSREG_BIT(TLBEHI_V); - sysreg_write(TLBEHI, tlbehi); - - /* Does this mapping already exist? */ - __builtin_tlbs(); - mmucr = sysreg_read(MMUCR); - - if (mmucr & SYSREG_BIT(MMUCR_N)) { - /* Not found -- pick a not-recently-accessed entry */ - unsigned int rp; - u32 tlbar = sysreg_read(TLBARLO); - - rp = 32 - fls(tlbar); - if (rp == 32) { - rp = 0; - sysreg_write(TLBARLO, -1L); - } - - mmucr = SYSREG_BFINS(DRP, rp, mmucr); - sysreg_write(MMUCR, mmucr); - } - - sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK); - - /* Let's go */ - __builtin_tlbw(); -} - -void update_mmu_cache(struct vm_area_struct *vma, - unsigned long address, pte_t *ptep) -{ - unsigned long flags; - - /* ptrace may call this routine */ - if (vma && current->active_mm != vma->vm_mm) - return; - - local_irq_save(flags); - update_dtlb(address, *ptep); - local_irq_restore(flags); -} - -static void __flush_tlb_page(unsigned long asid, unsigned long page) -{ - u32 mmucr, tlbehi; - - /* - * Caller is responsible for masking out non-PFN bits in page - * and changing the current ASID if necessary. This means that - * we don't need to flush the pipeline after writing TLBEHI. - */ - tlbehi = page | asid; - sysreg_write(TLBEHI, tlbehi); - - __builtin_tlbs(); - mmucr = sysreg_read(MMUCR); - - if (!(mmucr & SYSREG_BIT(MMUCR_N))) { - unsigned int entry; - u32 tlbarlo; - - /* Clear the "valid" bit */ - sysreg_write(TLBEHI, tlbehi); - - /* mark the entry as "not accessed" */ - entry = SYSREG_BFEXT(DRP, mmucr); - tlbarlo = sysreg_read(TLBARLO); - tlbarlo |= (0x80000000UL >> entry); - sysreg_write(TLBARLO, tlbarlo); - - /* update the entry with valid bit clear */ - __builtin_tlbw(); - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) { - unsigned long flags, asid; - unsigned long saved_asid = MMU_NO_ASID; - - asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK; - page &= PAGE_MASK; - - local_irq_save(flags); - if (vma->vm_mm != current->mm) { - saved_asid = get_asid(); - set_asid(asid); - } - - __flush_tlb_page(asid, page); - - if (saved_asid != MMU_NO_ASID) - set_asid(saved_asid); - local_irq_restore(flags); - } -} - -void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != NO_CONTEXT) { - unsigned long flags; - int size; - - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - - if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */ - mm->context = NO_CONTEXT; - if (mm == current->mm) - activate_context(mm); - } else { - unsigned long asid; - unsigned long saved_asid; - - asid = mm->context & MMU_CONTEXT_ASID_MASK; - saved_asid = MMU_NO_ASID; - - start &= PAGE_MASK; - end += (PAGE_SIZE - 1); - end &= PAGE_MASK; - - if (mm != current->mm) { - saved_asid = get_asid(); - set_asid(asid); - } - - while (start < end) { - __flush_tlb_page(asid, start); - start += PAGE_SIZE; - } - if (saved_asid != MMU_NO_ASID) - set_asid(saved_asid); - } - local_irq_restore(flags); - } -} - -/* - * This function depends on the pages to be flushed having the G - * (global) bit set in their pte. This is true for all - * PAGE_KERNEL(_RO) pages. - */ -void flush_tlb_kernel_range(unsigned long start, unsigned long end) -{ - unsigned long flags; - int size; - - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */ - flush_tlb_all(); - } else { - unsigned long asid; - - local_irq_save(flags); - asid = get_asid(); - - start &= PAGE_MASK; - end += (PAGE_SIZE - 1); - end &= PAGE_MASK; - - while (start < end) { - __flush_tlb_page(asid, start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - /* Invalidate all TLB entries of this process by getting a new ASID */ - if (mm->context != NO_CONTEXT) { - unsigned long flags; - - local_irq_save(flags); - mm->context = NO_CONTEXT; - if (mm == current->mm) - activate_context(mm); - local_irq_restore(flags); - } -} - -void flush_tlb_all(void) -{ - unsigned long flags; - - local_irq_save(flags); - sysreg_write(MMUCR, sysreg_read(MMUCR) | SYSREG_BIT(MMUCR_I)); - local_irq_restore(flags); -} - -#ifdef CONFIG_PROC_FS - -#include <linux/seq_file.h> -#include <linux/proc_fs.h> -#include <linux/init.h> - -static void *tlb_start(struct seq_file *tlb, loff_t *pos) -{ - static unsigned long tlb_index; - - if (*pos >= NR_TLB_ENTRIES) - return NULL; - - tlb_index = 0; - return &tlb_index; -} - -static void *tlb_next(struct seq_file *tlb, void *v, loff_t *pos) -{ - unsigned long *index = v; - - if (*index >= NR_TLB_ENTRIES - 1) - return NULL; - - ++*pos; - ++*index; - return index; -} - -static void tlb_stop(struct seq_file *tlb, void *v) -{ - -} - -static int tlb_show(struct seq_file *tlb, void *v) -{ - unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save; - unsigned long flags; - unsigned long *index = v; - - if (*index == 0) - seq_puts(tlb, "ID V G ASID VPN PFN AP SZ C B W D\n"); - - BUG_ON(*index >= NR_TLB_ENTRIES); - - local_irq_save(flags); - mmucr_save = sysreg_read(MMUCR); - tlbehi_save = sysreg_read(TLBEHI); - mmucr = SYSREG_BFINS(DRP, *index, mmucr_save); - sysreg_write(MMUCR, mmucr); - - /* TLBR might change the ASID */ - __builtin_tlbr(); - cpu_sync_pipeline(); - - tlbehi = sysreg_read(TLBEHI); - tlbelo = sysreg_read(TLBELO); - - sysreg_write(MMUCR, mmucr_save); - sysreg_write(TLBEHI, tlbehi_save); - cpu_sync_pipeline(); - local_irq_restore(flags); - - seq_printf(tlb, "%2lu: %c %c %02x %05x %05x %o %o %c %c %c %c\n", - *index, - SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0', - SYSREG_BFEXT(G, tlbelo) ? '1' : '0', - SYSREG_BFEXT(ASID, tlbehi), - SYSREG_BFEXT(VPN, tlbehi) >> 2, - SYSREG_BFEXT(PFN, tlbelo) >> 2, - SYSREG_BFEXT(AP, tlbelo), - SYSREG_BFEXT(SZ, tlbelo), - SYSREG_BFEXT(TLBELO_C, tlbelo) ? '1' : '0', - SYSREG_BFEXT(B, tlbelo) ? '1' : '0', - SYSREG_BFEXT(W, tlbelo) ? '1' : '0', - SYSREG_BFEXT(TLBELO_D, tlbelo) ? '1' : '0'); - - return 0; -} - -static const struct seq_operations tlb_ops = { - .start = tlb_start, - .next = tlb_next, - .stop = tlb_stop, - .show = tlb_show, -}; - -static int tlb_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &tlb_ops); -} - -static const struct file_operations proc_tlb_operations = { - .open = tlb_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init proctlb_init(void) -{ - proc_create("tlb", 0, NULL, &proc_tlb_operations); - return 0; -} -late_initcall(proctlb_init); -#endif /* CONFIG_PROC_FS */ diff --git a/arch/avr32/oprofile/Makefile b/arch/avr32/oprofile/Makefile deleted file mode 100644 index e0eb520e0287..000000000000 --- a/arch/avr32/oprofile/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-$(CONFIG_OPROFILE) += oprofile.o - -oprofile-y := $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o \ - timer_int.o) -oprofile-y += op_model_avr32.o backtrace.o diff --git a/arch/avr32/oprofile/backtrace.c b/arch/avr32/oprofile/backtrace.c deleted file mode 100644 index 75d9ad6f99cf..000000000000 --- a/arch/avr32/oprofile/backtrace.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * AVR32 specific backtracing code for oprofile - * - * Copyright 2008 Weinmann GmbH - * - * Author: Nikolaus Voss <n.voss@weinmann.de> - * - * Based on i386 oprofile backtrace code by John Levon and David Smith - * - * 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/oprofile.h> -#include <linux/sched.h> -#include <linux/uaccess.h> - -/* The first two words of each frame on the stack look like this if we have - * frame pointers */ -struct frame_head { - unsigned long lr; - struct frame_head *fp; -}; - -/* copied from arch/avr32/kernel/process.c */ -static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) -{ - return (p > (unsigned long)tinfo) - && (p < (unsigned long)tinfo + THREAD_SIZE - 3); -} - -/* copied from arch/x86/oprofile/backtrace.c */ -static struct frame_head *dump_user_backtrace(struct frame_head *head) -{ - struct frame_head bufhead[2]; - - /* Also check accessibility of one struct frame_head beyond */ - if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) - return NULL; - if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) - return NULL; - - oprofile_add_trace(bufhead[0].lr); - - /* frame pointers should strictly progress back up the stack - * (towards higher addresses) */ - if (bufhead[0].fp <= head) - return NULL; - - return bufhead[0].fp; -} - -void avr32_backtrace(struct pt_regs * const regs, unsigned int depth) -{ - /* Get first frame pointer */ - struct frame_head *head = (struct frame_head *)(regs->r7); - - if (!user_mode(regs)) { -#ifdef CONFIG_FRAME_POINTER - /* - * Traverse the kernel stack from frame to frame up to - * "depth" steps. - */ - while (depth-- && valid_stack_ptr(task_thread_info(current), - (unsigned long)head)) { - oprofile_add_trace(head->lr); - if (head->fp <= head) - break; - head = head->fp; - } -#endif - } else { - /* Assume we have frame pointers in user mode process */ - while (depth-- && head) - head = dump_user_backtrace(head); - } -} - - diff --git a/arch/avr32/oprofile/op_model_avr32.c b/arch/avr32/oprofile/op_model_avr32.c deleted file mode 100644 index 08308be2c02c..000000000000 --- a/arch/avr32/oprofile/op_model_avr32.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * AVR32 Performance Counter Driver - * - * Copyright (C) 2005-2007 Atmel Corporation - * - * 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. - * - * Author: Ronny Pedersen - */ -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/oprofile.h> -#include <linux/sched.h> -#include <linux/types.h> - -#include <asm/sysreg.h> - -#define AVR32_PERFCTR_IRQ_GROUP 0 -#define AVR32_PERFCTR_IRQ_LINE 1 - -void avr32_backtrace(struct pt_regs * const regs, unsigned int depth); - -enum { PCCNT, PCNT0, PCNT1, NR_counter }; - -struct avr32_perf_counter { - unsigned long enabled; - unsigned long event; - unsigned long count; - unsigned long unit_mask; - unsigned long kernel; - unsigned long user; - - u32 ie_mask; - u32 flag_mask; -}; - -static struct avr32_perf_counter counter[NR_counter] = { - { - .ie_mask = SYSREG_BIT(IEC), - .flag_mask = SYSREG_BIT(FC), - }, { - .ie_mask = SYSREG_BIT(IE0), - .flag_mask = SYSREG_BIT(F0), - }, { - .ie_mask = SYSREG_BIT(IE1), - .flag_mask = SYSREG_BIT(F1), - }, -}; - -static void avr32_perf_counter_reset(void) -{ - /* Reset all counter and disable/clear all interrupts */ - sysreg_write(PCCR, (SYSREG_BIT(PCCR_R) - | SYSREG_BIT(PCCR_C) - | SYSREG_BIT(FC) - | SYSREG_BIT(F0) - | SYSREG_BIT(F1))); -} - -static irqreturn_t avr32_perf_counter_interrupt(int irq, void *dev_id) -{ - struct avr32_perf_counter *ctr = dev_id; - struct pt_regs *regs; - u32 pccr; - - if (likely(!(intc_get_pending(AVR32_PERFCTR_IRQ_GROUP) - & (1 << AVR32_PERFCTR_IRQ_LINE)))) - return IRQ_NONE; - - regs = get_irq_regs(); - pccr = sysreg_read(PCCR); - - /* Clear the interrupt flags we're about to handle */ - sysreg_write(PCCR, pccr); - - /* PCCNT */ - if (ctr->enabled && (pccr & ctr->flag_mask)) { - sysreg_write(PCCNT, -ctr->count); - oprofile_add_sample(regs, PCCNT); - } - ctr++; - /* PCNT0 */ - if (ctr->enabled && (pccr & ctr->flag_mask)) { - sysreg_write(PCNT0, -ctr->count); - oprofile_add_sample(regs, PCNT0); - } - ctr++; - /* PCNT1 */ - if (ctr->enabled && (pccr & ctr->flag_mask)) { - sysreg_write(PCNT1, -ctr->count); - oprofile_add_sample(regs, PCNT1); - } - - return IRQ_HANDLED; -} - -static int avr32_perf_counter_create_files(struct dentry *root) -{ - struct dentry *dir; - unsigned int i; - char filename[4]; - - for (i = 0; i < NR_counter; i++) { - snprintf(filename, sizeof(filename), "%u", i); - dir = oprofilefs_mkdir(root, filename); - - oprofilefs_create_ulong(dir, "enabled", - &counter[i].enabled); - oprofilefs_create_ulong(dir, "event", - &counter[i].event); - oprofilefs_create_ulong(dir, "count", - &counter[i].count); - - /* Dummy entries */ - oprofilefs_create_ulong(dir, "kernel", - &counter[i].kernel); - oprofilefs_create_ulong(dir, "user", - &counter[i].user); - oprofilefs_create_ulong(dir, "unit_mask", - &counter[i].unit_mask); - } - - return 0; -} - -static int avr32_perf_counter_setup(void) -{ - struct avr32_perf_counter *ctr; - u32 pccr; - int ret; - int i; - - pr_debug("avr32_perf_counter_setup\n"); - - if (sysreg_read(PCCR) & SYSREG_BIT(PCCR_E)) { - printk(KERN_ERR - "oprofile: setup: perf counter already enabled\n"); - return -EBUSY; - } - - ret = request_irq(AVR32_PERFCTR_IRQ_GROUP, - avr32_perf_counter_interrupt, IRQF_SHARED, - "oprofile", counter); - if (ret) - return ret; - - avr32_perf_counter_reset(); - - pccr = 0; - for (i = PCCNT; i < NR_counter; i++) { - ctr = &counter[i]; - if (!ctr->enabled) - continue; - - pr_debug("enabling counter %d...\n", i); - - pccr |= ctr->ie_mask; - - switch (i) { - case PCCNT: - /* PCCNT always counts cycles, so no events */ - sysreg_write(PCCNT, -ctr->count); - break; - case PCNT0: - pccr |= SYSREG_BF(CONF0, ctr->event); - sysreg_write(PCNT0, -ctr->count); - break; - case PCNT1: - pccr |= SYSREG_BF(CONF1, ctr->event); - sysreg_write(PCNT1, -ctr->count); - break; - } - } - - pr_debug("oprofile: writing 0x%x to PCCR...\n", pccr); - - sysreg_write(PCCR, pccr); - - return 0; -} - -static void avr32_perf_counter_shutdown(void) -{ - pr_debug("avr32_perf_counter_shutdown\n"); - - avr32_perf_counter_reset(); - free_irq(AVR32_PERFCTR_IRQ_GROUP, counter); -} - -static int avr32_perf_counter_start(void) -{ - pr_debug("avr32_perf_counter_start\n"); - - sysreg_write(PCCR, sysreg_read(PCCR) | SYSREG_BIT(PCCR_E)); - - return 0; -} - -static void avr32_perf_counter_stop(void) -{ - pr_debug("avr32_perf_counter_stop\n"); - - sysreg_write(PCCR, sysreg_read(PCCR) & ~SYSREG_BIT(PCCR_E)); -} - -static struct oprofile_operations avr32_perf_counter_ops __initdata = { - .create_files = avr32_perf_counter_create_files, - .setup = avr32_perf_counter_setup, - .shutdown = avr32_perf_counter_shutdown, - .start = avr32_perf_counter_start, - .stop = avr32_perf_counter_stop, - .cpu_type = "avr32", -}; - -int __init oprofile_arch_init(struct oprofile_operations *ops) -{ - if (!(current_cpu_data.features & AVR32_FEATURE_PCTR)) - return -ENODEV; - - memcpy(ops, &avr32_perf_counter_ops, - sizeof(struct oprofile_operations)); - - ops->backtrace = avr32_backtrace; - - printk(KERN_INFO "oprofile: using AVR32 performance monitoring.\n"); - - return 0; -} - -void oprofile_arch_exit(void) -{ - -} diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild index 625db8ac815e..dc4ef9ac1e83 100644 --- a/arch/blackfin/include/asm/Kbuild +++ b/arch/blackfin/include/asm/Kbuild @@ -7,6 +7,7 @@ generic-y += device.h generic-y += div64.h generic-y += emergency-restart.h generic-y += errno.h +generic-y += extable.h generic-y += fb.h generic-y += futex.h generic-y += hw_irq.h diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 0eff88aa6d6a..f54a34f31cea 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h @@ -12,7 +12,6 @@ /* * User space memory access functions */ -#include <linux/sched.h> #include <linux/mm.h> #include <linux/string.h> @@ -29,9 +28,6 @@ static inline void set_fs(mm_segment_t fs) #define segment_eq(a, b) ((a) == (b)) -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define access_ok(type, addr, size) _access_ok((unsigned long)(addr), (size)) /* @@ -46,22 +42,7 @@ static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; extern int _access_ok(unsigned long addr, unsigned long size); #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; -}; +#include <asm/extable.h> /* * These are the main single-value transfer routines. They automatically @@ -163,41 +144,23 @@ static inline int bad_user_access_length(void) : "a" (__ptr(ptr))); \ }) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - static inline unsigned long __must_check -__copy_from_user(void *to, const void __user *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { memcpy(to, (const void __force *)from, n); return 0; } static inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { memcpy((void __force *)to, from, n); SSYNC(); return 0; } -static inline unsigned long __must_check -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_READ, from, n))) - return __copy_from_user(to, from, n); - memset(to, 0, n); - return n; -} - -static inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_WRITE, to, n))) - return __copy_to_user(to, from, n); - return n; -} - +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * Copy a null terminated string from userspace. */ diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 89d5162d4ca6..89814850b08b 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -370,7 +370,7 @@ int _access_ok(unsigned long addr, unsigned long size) /* Check that things do not wrap around */ if (addr > ULONG_MAX - size) return 0; - if (segment_eq(get_fs(), KERNEL_DS)) + if (uaccess_kernel()) return 1; #ifdef CONFIG_MTD_UCLINUX if (1) diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 0e9fcf841d67..01350557fbd7 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -230,7 +230,9 @@ static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt) clock_tick = get_sclk(); evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(-1, evt); + evt->max_delta_ticks = (unsigned long)-1; evt->min_delta_ns = clockevent_delta2ns(100, evt); + evt->min_delta_ticks = 100; evt->cpumask = cpumask_of(0); @@ -344,7 +346,9 @@ void bfin_coretmr_clockevent_init(void) clock_tick = get_cclk() / TIME_SCALE; evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(-1, evt); + evt->max_delta_ticks = (unsigned long)-1; evt->min_delta_ns = clockevent_delta2ns(100, evt); + evt->min_delta_ticks = 100; evt->cpumask = cpumask_of(cpu); diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 68069a120055..334ef8139b35 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -115,6 +115,8 @@ SECTIONS __data_lma = LOADADDR(.data); __data_len = SIZEOF(.data); + BUG_TABLE + /* The init section should be last, so when we free it, it goes into * the general memory pool, and (hopefully) will decrease fragmentation * a tiny bit. The init section has a _requirement_ that it be diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index 82619c32d25b..f0eaf0475e7e 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -12,6 +12,7 @@ generic-y += dma.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += futex.h diff --git a/arch/c6x/include/asm/uaccess.h b/arch/c6x/include/asm/uaccess.h index 453dd263bee3..ba6756879f00 100644 --- a/arch/c6x/include/asm/uaccess.h +++ b/arch/c6x/include/asm/uaccess.h @@ -13,17 +13,11 @@ #include <linux/compiler.h> #include <linux/string.h> -#ifdef CONFIG_ACCESS_CHECK -#define __access_ok _access_ok -#endif - /* - * __copy_from_user/copy_to_user are based on ones in asm-generic/uaccess.h - * * C6X supports unaligned 32 and 64 bit loads and stores. */ -static inline __must_check long __copy_from_user(void *to, - const void __user *from, unsigned long n) +static inline __must_check unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { u32 tmp32; u64 tmp64; @@ -58,8 +52,8 @@ static inline __must_check long __copy_from_user(void *to, return 0; } -static inline __must_check long __copy_to_user(void __user *to, - const void *from, unsigned long n) +static inline __must_check unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { u32 tmp32; u64 tmp64; @@ -93,9 +87,8 @@ static inline __must_check long __copy_to_user(void __user *to, memcpy((void __force *)to, from, n); return 0; } - -#define __copy_to_user __copy_to_user -#define __copy_from_user __copy_from_user +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER extern int _access_ok(unsigned long addr, unsigned long size); #ifdef CONFIG_ACCESS_CHECK diff --git a/arch/c6x/kernel/ptrace.c b/arch/c6x/kernel/ptrace.c index a27e1f02ce18..8801dc98fd44 100644 --- a/arch/c6x/kernel/ptrace.c +++ b/arch/c6x/kernel/ptrace.c @@ -70,46 +70,6 @@ static int gpr_get(struct task_struct *target, 0, sizeof(*regs)); } -static int gpr_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - struct pt_regs *regs = task_pt_regs(target); - - /* Don't copyin TSR or CSR */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s, - 0, PT_TSR * sizeof(long)); - if (ret) - return ret; - - ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, - PT_TSR * sizeof(long), - (PT_TSR + 1) * sizeof(long)); - if (ret) - return ret; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s, - (PT_TSR + 1) * sizeof(long), - PT_CSR * sizeof(long)); - if (ret) - return ret; - - ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, - PT_CSR * sizeof(long), - (PT_CSR + 1) * sizeof(long)); - if (ret) - return ret; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s, - (PT_CSR + 1) * sizeof(long), -1); - return ret; -} - enum c6x_regset { REGSET_GPR, }; @@ -121,7 +81,6 @@ static const struct user_regset c6x_regsets[] = { .size = sizeof(u32), .align = sizeof(u32), .get = gpr_get, - .set = gpr_set }, }; diff --git a/arch/c6x/kernel/sys_c6x.c b/arch/c6x/kernel/sys_c6x.c index 3e9bdfbee8ad..a742ae259239 100644 --- a/arch/c6x/kernel/sys_c6x.c +++ b/arch/c6x/kernel/sys_c6x.c @@ -23,7 +23,7 @@ int _access_ok(unsigned long addr, unsigned long size) if (!addr || addr > (0xffffffffUL - (size - 1))) goto _bad_access; - if (segment_eq(get_fs(), KERNEL_DS)) + if (uaccess_kernel()) return 1; if (memory_start <= addr && (addr + size - 1) < memory_end) diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S index a1a5c166bc9b..29ebea49ddd5 100644 --- a/arch/c6x/kernel/vmlinux.lds.S +++ b/arch/c6x/kernel/vmlinux.lds.S @@ -128,6 +128,8 @@ SECTIONS . = ALIGN(8); } + BUG_TABLE + _edata = .; __bss_start = .; diff --git a/arch/c6x/platforms/timer64.c b/arch/c6x/platforms/timer64.c index c19901e5f055..0bd0452ded80 100644 --- a/arch/c6x/platforms/timer64.c +++ b/arch/c6x/platforms/timer64.c @@ -234,7 +234,9 @@ void __init timer64_init(void) clockevents_calc_mult_shift(cd, c6x_core_freq / TIMER_DIVISOR, 5); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(250, cd); + cd->min_delta_ticks = 250; cd->cpumask = cpumask_of(smp_processor_id()); diff --git a/arch/cris/arch-v10/lib/usercopy.c b/arch/cris/arch-v10/lib/usercopy.c index 1ba7cc000dfc..48fa37fe0f9b 100644 --- a/arch/cris/arch-v10/lib/usercopy.c +++ b/arch/cris/arch-v10/lib/usercopy.c @@ -188,11 +188,10 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, unsigned long pn) } EXPORT_SYMBOL(__copy_user); -/* Copy from user to kernel, zeroing the bytes that were inaccessible in - userland. The return-value is the number of bytes that were +/* Copy from user to kernel. The return-value is the number of bytes that were inaccessible. */ -unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, +unsigned long __copy_user_in(void *pdst, const void __user *psrc, unsigned long pn) { /* We want the parameters put in special registers. @@ -217,19 +216,17 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, { __asm_copy_from_user_1 (dst, src, retn); n--; + if (retn) + goto exception; } if (((unsigned long) src & 2) && n >= 2) { __asm_copy_from_user_2 (dst, src, retn); n -= 2; + if (retn) + goto exception; } - - /* We only need one check after the unalignment-adjustments, because - if both adjustments were done, either both or neither reference - had an exception. */ - if (retn != 0) - goto copy_exception_bytes; } /* Decide which copying method to use. */ @@ -328,7 +325,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, n -= 4; if (retn) - goto copy_exception_bytes; + goto exception; } /* If we get here, there were no memory read faults. */ @@ -356,20 +353,10 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, bytes. */ return retn; -copy_exception_bytes: - /* We already have "retn" bytes cleared, and need to clear the - remaining "n" bytes. A non-optimized simple byte-for-byte in-line - memset is preferred here, since this isn't speed-critical code and - we'd rather have this a leaf-function than calling memset. */ - { - char *endp; - for (endp = dst + n; dst < endp; dst++) - *dst = 0; - } - +exception: return retn + n; } -EXPORT_SYMBOL(__copy_user_zeroing); +EXPORT_SYMBOL(__copy_user_in); /* Zero userspace. */ unsigned long __do_clear_user(void __user *pto, unsigned long pn) diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index ae6903d7fdbe..14970f11bbf2 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -2086,7 +2086,7 @@ static void cryptocop_job_queue_close(void) dma_in_cfg.en = regk_dma_no; REG_WR(dma, IN_DMA_INST, rw_cfg, dma_in_cfg); - /* Disble the cryptocop. */ + /* Disable the cryptocop. */ rw_cfg = REG_RD(strcop, regi_strcop, rw_cfg); rw_cfg.en = 0; REG_WR(strcop, regi_strcop, rw_cfg, rw_cfg); diff --git a/arch/cris/arch-v32/lib/usercopy.c b/arch/cris/arch-v32/lib/usercopy.c index 05e58dab800d..20b608026913 100644 --- a/arch/cris/arch-v32/lib/usercopy.c +++ b/arch/cris/arch-v32/lib/usercopy.c @@ -156,10 +156,9 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, unsigned long pn) } EXPORT_SYMBOL(__copy_user); -/* Copy from user to kernel, zeroing the bytes that were inaccessible in - userland. The return-value is the number of bytes that were +/* Copy from user to kernel. The return-value is the number of bytes that were inaccessible. */ -unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, +unsigned long __copy_user_in(void *pdst, const void __user *psrc, unsigned long pn) { /* We want the parameters put in special registers. @@ -184,19 +183,18 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, { __asm_copy_from_user_1 (dst, src, retn); n--; + if (retn != 0) + goto exception; } if (((unsigned long) src & 2) && n >= 2) { __asm_copy_from_user_2 (dst, src, retn); n -= 2; + if (retn != 0) + goto exception; } - /* We only need one check after the unalignment-adjustments, because - if both adjustments were done, either both or neither reference - had an exception. */ - if (retn != 0) - goto copy_exception_bytes; } /* Movem is dirt cheap. The overheap is low enough to always use the @@ -279,7 +277,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, n -= 4; if (retn) - goto copy_exception_bytes; + goto exception; } /* If we get here, there were no memory read faults. */ @@ -307,20 +305,10 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, bytes. */ return retn; -copy_exception_bytes: - /* We already have "retn" bytes cleared, and need to clear the - remaining "n" bytes. A non-optimized simple byte-for-byte in-line - memset is preferred here, since this isn't speed-critical code and - we'd rather have this a leaf-function than calling memset. */ - { - char *endp; - for (endp = dst + n; dst < endp; dst++) - *dst = 0; - } - +exception: return retn + n; } -EXPORT_SYMBOL(__copy_user_zeroing); +EXPORT_SYMBOL(__copy_user_in); /* Zero userspace. */ unsigned long __do_clear_user(void __user *pto, unsigned long pn) diff --git a/arch/cris/include/arch-v10/arch/uaccess.h b/arch/cris/include/arch-v10/arch/uaccess.h index 65b02d9b605a..5477c98c2281 100644 --- a/arch/cris/include/arch-v10/arch/uaccess.h +++ b/arch/cris/include/arch-v10/arch/uaccess.h @@ -172,16 +172,14 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_user_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "2: move.b $r9,[%0+]\n", \ - "3: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "3: addq 1,%2\n", \ " .dword 2b,3b\n") #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ __asm_copy_user_cont(to, from, ret, \ " move.w [%1+],$r9\n" \ "2: move.w $r9,[%0+]\n" COPY, \ - "3: addq 2,%2\n" \ - " clear.w [%0+]\n" FIXUP, \ + "3: addq 2,%2\n" FIXUP, \ " .dword 2b,3b\n" TENTRY) #define __asm_copy_from_user_2(to, from, ret) \ @@ -191,16 +189,14 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_2x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "4: move.b $r9,[%0+]\n", \ - "5: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "5: addq 1,%2\n", \ " .dword 4b,5b\n") #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ __asm_copy_user_cont(to, from, ret, \ " move.d [%1+],$r9\n" \ "2: move.d $r9,[%0+]\n" COPY, \ - "3: addq 4,%2\n" \ - " clear.d [%0+]\n" FIXUP, \ + "3: addq 4,%2\n" FIXUP, \ " .dword 2b,3b\n" TENTRY) #define __asm_copy_from_user_4(to, from, ret) \ @@ -210,8 +206,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_4x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "4: move.b $r9,[%0+]\n", \ - "5: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "5: addq 1,%2\n", \ " .dword 4b,5b\n") #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -219,7 +214,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.w [%1+],$r9\n" \ "4: move.w $r9,[%0+]\n" COPY, \ "5: addq 2,%2\n" \ - " clear.w [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 4b,5b\n" TENTRY) #define __asm_copy_from_user_6(to, from, ret) \ @@ -229,8 +224,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_6x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "6: move.b $r9,[%0+]\n", \ - "7: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "7: addq 1,%2\n", \ " .dword 6b,7b\n") #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -238,7 +232,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.d [%1+],$r9\n" \ "4: move.d $r9,[%0+]\n" COPY, \ "5: addq 4,%2\n" \ - " clear.d [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 4b,5b\n" TENTRY) #define __asm_copy_from_user_8(to, from, ret) \ @@ -248,8 +242,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_8x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "6: move.b $r9,[%0+]\n", \ - "7: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "7: addq 1,%2\n", \ " .dword 6b,7b\n") #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -257,7 +250,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.w [%1+],$r9\n" \ "6: move.w $r9,[%0+]\n" COPY, \ "7: addq 2,%2\n" \ - " clear.w [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 6b,7b\n" TENTRY) #define __asm_copy_from_user_10(to, from, ret) \ @@ -267,8 +260,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_10x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "8: move.b $r9,[%0+]\n", \ - "9: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "9: addq 1,%2\n", \ " .dword 8b,9b\n") #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -276,7 +268,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.d [%1+],$r9\n" \ "6: move.d $r9,[%0+]\n" COPY, \ "7: addq 4,%2\n" \ - " clear.d [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 6b,7b\n" TENTRY) #define __asm_copy_from_user_12(to, from, ret) \ @@ -286,8 +278,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_12x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "8: move.b $r9,[%0+]\n", \ - "9: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "9: addq 1,%2\n", \ " .dword 8b,9b\n") #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -295,7 +286,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.w [%1+],$r9\n" \ "8: move.w $r9,[%0+]\n" COPY, \ "9: addq 2,%2\n" \ - " clear.w [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 8b,9b\n" TENTRY) #define __asm_copy_from_user_14(to, from, ret) \ @@ -305,8 +296,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_14x_cont(to, from, ret, \ " move.b [%1+],$r9\n" \ "10: move.b $r9,[%0+]\n", \ - "11: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "11: addq 1,%2\n", \ " .dword 10b,11b\n") #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -314,7 +304,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.d [%1+],$r9\n" \ "8: move.d $r9,[%0+]\n" COPY, \ "9: addq 4,%2\n" \ - " clear.d [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 8b,9b\n" TENTRY) #define __asm_copy_from_user_16(to, from, ret) \ @@ -325,7 +315,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.d [%1+],$r9\n" \ "10: move.d $r9,[%0+]\n" COPY, \ "11: addq 4,%2\n" \ - " clear.d [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 10b,11b\n" TENTRY) #define __asm_copy_from_user_20(to, from, ret) \ @@ -336,7 +326,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.d [%1+],$r9\n" \ "12: move.d $r9,[%0+]\n" COPY, \ "13: addq 4,%2\n" \ - " clear.d [%0+]\n" FIXUP, \ + FIXUP, \ " .dword 12b,13b\n" TENTRY) #define __asm_copy_from_user_24(to, from, ret) \ diff --git a/arch/cris/include/arch-v32/arch/uaccess.h b/arch/cris/include/arch-v32/arch/uaccess.h index 3196019706cb..dc2ce090f624 100644 --- a/arch/cris/include/arch-v32/arch/uaccess.h +++ b/arch/cris/include/arch-v32/arch/uaccess.h @@ -178,8 +178,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "2: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ "3: addq 1,%2\n" \ - " jump 1b\n" \ - " clear.b [%0+]\n", \ + " jump 1b\n", \ " .dword 2b,3b\n") #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -189,8 +188,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.w $acr,[%0+]\n", \ FIXUP \ "3: addq 2,%2\n" \ - " jump 1b\n" \ - " clear.w [%0+]\n", \ + " jump 1b\n", \ TENTRY \ " .dword 2b,3b\n") @@ -201,8 +199,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_2x_cont(to, from, ret, \ "4: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "5: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "5: addq 1,%2\n", \ " .dword 4b,5b\n") #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -212,8 +209,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) " move.d $acr,[%0+]\n", \ FIXUP \ "3: addq 4,%2\n" \ - " jump 1b\n" \ - " clear.d [%0+]\n", \ + " jump 1b\n", \ TENTRY \ " .dword 2b,3b\n") @@ -224,8 +220,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_4x_cont(to, from, ret, \ "4: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "5: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "5: addq 1,%2\n", \ " .dword 4b,5b\n") #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -234,8 +229,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "4: move.w [%1+],$acr\n" \ " move.w $acr,[%0+]\n", \ FIXUP \ - "5: addq 2,%2\n" \ - " clear.w [%0+]\n", \ + "5: addq 2,%2\n", \ TENTRY \ " .dword 4b,5b\n") @@ -246,8 +240,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_6x_cont(to, from, ret, \ "6: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "7: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "7: addq 1,%2\n", \ " .dword 6b,7b\n") #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -256,8 +249,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "4: move.d [%1+],$acr\n" \ " move.d $acr,[%0+]\n", \ FIXUP \ - "5: addq 4,%2\n" \ - " clear.d [%0+]\n", \ + "5: addq 4,%2\n", \ TENTRY \ " .dword 4b,5b\n") @@ -268,8 +260,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_8x_cont(to, from, ret, \ "6: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "7: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "7: addq 1,%2\n", \ " .dword 6b,7b\n") #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -278,8 +269,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "6: move.w [%1+],$acr\n" \ " move.w $acr,[%0+]\n", \ FIXUP \ - "7: addq 2,%2\n" \ - " clear.w [%0+]\n", \ + "7: addq 2,%2\n", \ TENTRY \ " .dword 6b,7b\n") @@ -290,8 +280,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_10x_cont(to, from, ret, \ "8: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "9: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "9: addq 1,%2\n", \ " .dword 8b,9b\n") #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -300,8 +289,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "6: move.d [%1+],$acr\n" \ " move.d $acr,[%0+]\n", \ FIXUP \ - "7: addq 4,%2\n" \ - " clear.d [%0+]\n", \ + "7: addq 4,%2\n", \ TENTRY \ " .dword 6b,7b\n") @@ -312,8 +300,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_12x_cont(to, from, ret, \ "8: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "9: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "9: addq 1,%2\n", \ " .dword 8b,9b\n") #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -322,8 +309,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "8: move.w [%1+],$acr\n" \ " move.w $acr,[%0+]\n", \ FIXUP \ - "9: addq 2,%2\n" \ - " clear.w [%0+]\n", \ + "9: addq 2,%2\n", \ TENTRY \ " .dword 8b,9b\n") @@ -334,8 +320,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm_copy_from_user_14x_cont(to, from, ret, \ "10: move.b [%1+],$acr\n" \ " move.b $acr,[%0+]\n", \ - "11: addq 1,%2\n" \ - " clear.b [%0+]\n", \ + "11: addq 1,%2\n", \ " .dword 10b,11b\n") #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ @@ -344,8 +329,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "8: move.d [%1+],$acr\n" \ " move.d $acr,[%0+]\n", \ FIXUP \ - "9: addq 4,%2\n" \ - " clear.d [%0+]\n", \ + "9: addq 4,%2\n", \ TENTRY \ " .dword 8b,9b\n") @@ -358,8 +342,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "10: move.d [%1+],$acr\n" \ " move.d $acr,[%0+]\n", \ FIXUP \ - "11: addq 4,%2\n" \ - " clear.d [%0+]\n", \ + "11: addq 4,%2\n", \ TENTRY \ " .dword 10b,11b\n") @@ -372,8 +355,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) "12: move.d [%1+],$acr\n" \ " move.d $acr,[%0+]\n", \ FIXUP \ - "13: addq 4,%2\n" \ - " clear.d [%0+]\n", \ + "13: addq 4,%2\n", \ TENTRY \ " .dword 12b,13b\n") diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index 0f5132b08896..2890099992a9 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -9,6 +9,7 @@ generic-y += device.h generic-y += div64.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += emergency-restart.h generic-y += fcntl.h generic-y += futex.h diff --git a/arch/cris/include/asm/pgtable.h b/arch/cris/include/asm/pgtable.h index 2a3210ba4c72..fa3a73004cc5 100644 --- a/arch/cris/include/asm/pgtable.h +++ b/arch/cris/include/asm/pgtable.h @@ -6,6 +6,7 @@ #define _CRIS_PGTABLE_H #include <asm/page.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #ifndef __ASSEMBLY__ diff --git a/arch/cris/include/asm/uaccess.h b/arch/cris/include/asm/uaccess.h index 56c7d5750abd..0d473aec3066 100644 --- a/arch/cris/include/asm/uaccess.h +++ b/arch/cris/include/asm/uaccess.h @@ -15,15 +15,9 @@ #ifndef _CRIS_UACCESS_H #define _CRIS_UACCESS_H -#ifndef __ASSEMBLY__ -#include <linux/sched.h> -#include <linux/errno.h> #include <asm/processor.h> #include <asm/page.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - /* * The fs value determines whether argument validity checking should be * performed or not. If get_fs() == USER_DS, checking is performed, with @@ -49,30 +43,14 @@ #define segment_eq(a, b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) +#define __kernel_ok (uaccess_kernel()) #define __user_ok(addr, size) \ (((size) <= TASK_SIZE) && ((addr) <= TASK_SIZE-(size))) #define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), (size)) #include <arch/uaccess.h> - -/* - * 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; -}; +#include <asm/extable.h> /* * These are the main single-value transfer routines. They automatically @@ -191,7 +169,7 @@ extern long __get_user_bad(void); live in lib/usercopy.c */ extern unsigned long __copy_user(void __user *to, const void *from, unsigned long n); -extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n); +extern unsigned long __copy_user_in(void *to, const void __user *from, unsigned long n); extern unsigned long __do_clear_user(void __user *to, unsigned long n); static inline long @@ -258,7 +236,7 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n) else if (n == 24) __asm_copy_from_user_24(to, from, ret); else - ret = __copy_user_zeroing(to, from, n); + ret = __copy_user_in(to, from, n); return ret; } @@ -358,64 +336,33 @@ static inline size_t clear_user(void __user *to, size_t n) return __do_clear_user(to, n); } -static inline size_t copy_from_user(void *to, const void __user *from, size_t n) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - if (unlikely(!access_ok(VERIFY_READ, from, n))) { - memset(to, 0, n); - return n; - } if (__builtin_constant_p(n)) return __constant_copy_from_user(to, from, n); else - return __copy_user_zeroing(to, from, n); + return __copy_user_in(to, from, n); } -static inline size_t copy_to_user(void __user *to, const void *from, size_t n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - if (unlikely(!access_ok(VERIFY_WRITE, to, n))) - return n; if (__builtin_constant_p(n)) return __constant_copy_to_user(to, from, n); else return __copy_user(to, from, n); } -/* We let the __ versions of copy_from/to_user inline, because they're often - * used in fast paths and have only a small space overhead. - */ +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER static inline unsigned long -__generic_copy_from_user_nocheck(void *to, const void __user *from, - unsigned long n) -{ - return __copy_user_zeroing(to, from, n); -} - -static inline unsigned long -__generic_copy_to_user_nocheck(void __user *to, const void *from, - unsigned long n) -{ - return __copy_user(to, from, n); -} - -static inline unsigned long -__generic_clear_user_nocheck(void __user *to, unsigned long n) +__clear_user(void __user *to, unsigned long n) { return __do_clear_user(to, n); } -/* without checking */ - -#define __copy_to_user(to, from, n) \ - __generic_copy_to_user_nocheck((to), (from), (n)) -#define __copy_from_user(to, from, n) \ - __generic_copy_from_user_nocheck((to), (from), (n)) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user -#define __clear_user(to, n) __generic_clear_user_nocheck((to), (n)) - #define strlen_user(str) strnlen_user((str), 0x7ffffffe) -#endif /* __ASSEMBLY__ */ - #endif /* _CRIS_UACCESS_H */ diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index 979586261520..867f237d7c5c 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -68,6 +68,8 @@ SECTIONS __edata = . ; /* End of data section. */ _edata = . ; + BUG_TABLE + INIT_TASK_DATA_SECTION(PAGE_SIZE) . = ALIGN(PAGE_SIZE); /* Init code and data. */ diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index c33b46715f65..cce3bc3603ea 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@ -1,6 +1,7 @@ generic-y += clkdev.h generic-y += exec.h +generic-y += extable.h generic-y += irq_work.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h diff --git a/arch/frv/include/asm/pgtable.h b/arch/frv/include/asm/pgtable.h index a0513d463a1f..ab6e7e961b54 100644 --- a/arch/frv/include/asm/pgtable.h +++ b/arch/frv/include/asm/pgtable.h @@ -16,6 +16,7 @@ #ifndef _ASM_PGTABLE_H #define _ASM_PGTABLE_H +#include <asm-generic/5level-fixup.h> #include <asm/mem-layout.h> #include <asm/setup.h> #include <asm/processor.h> diff --git a/arch/frv/include/asm/uaccess.h b/arch/frv/include/asm/uaccess.h index c0f4057eab60..e4e33b4cd3ae 100644 --- a/arch/frv/include/asm/uaccess.h +++ b/arch/frv/include/asm/uaccess.h @@ -15,16 +15,13 @@ /* * User space memory access functions */ -#include <linux/sched.h> #include <linux/mm.h> #include <asm/segment.h> #include <asm/sections.h> +#include <asm/extable.h> #define __ptr(x) ((unsigned long __force *)(x)) -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - /* * check that a range of addresses falls within the current address limit */ @@ -63,26 +60,6 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) #define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0) #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0) -/* - * 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); - /* * These are the main single-value transfer routines. They automatically @@ -256,61 +233,50 @@ do { \ /* * */ + #define ____force(x) (__force void *)(void __user *)(x) #ifdef CONFIG_MMU extern long __memset_user(void *dst, unsigned long count); extern long __memcpy_user(void *dst, const void *src, unsigned long count); #define __clear_user(dst,count) __memset_user(____force(dst), (count)) -#define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), ____force(from), (n)) -#define __copy_to_user_inatomic(to, from, n) __memcpy_user(____force(to), (from), (n)) #else #define __clear_user(dst,count) (memset(____force(dst), 0, (count)), 0) -#define __copy_from_user_inatomic(to, from, n) (memcpy((to), ____force(from), (n)), 0) -#define __copy_to_user_inatomic(to, from, n) (memcpy(____force(to), (from), (n)), 0) #endif -static inline unsigned long __must_check -clear_user(void __user *to, unsigned long n) -{ - if (likely(__access_ok(to, n))) - n = __clear_user(to, n); - return n; -} - -static inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) -{ - might_fault(); - return __copy_to_user_inatomic(to, from, n); -} - static inline unsigned long -__copy_from_user(void *to, const void __user *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - might_fault(); - return __copy_from_user_inatomic(to, from, n); +#ifdef CONFIG_MMU + return __memcpy_user(to, (__force const void *)from, n); +#else + memcpy(to, (__force const void *)from, n); + return 0; +#endif } -static inline long copy_from_user(void *to, const void __user *from, unsigned long n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - unsigned long ret = n; - - if (likely(__access_ok(from, n))) - ret = __copy_from_user(to, from, n); - - if (unlikely(ret != 0)) - memset(to + (n - ret), 0, ret); - - return ret; +#ifdef CONFIG_MMU + return __memcpy_user((__force void *)to, from, n); +#else + memcpy((__force void *)to, from, n); + return 0; +#endif } +#define INLINE_COPY_TO_USER +#define INLINE_COPY_FROM_USER -static inline long copy_to_user(void __user *to, const void *from, unsigned long n) +static inline unsigned long __must_check +clear_user(void __user *to, unsigned long n) { - return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n; + if (likely(__access_ok(to, n))) + n = __clear_user(to, n); + return n; } extern long strncpy_from_user(char *dst, const char __user *src, long count); @@ -318,6 +284,4 @@ extern long strnlen_user(const char __user *src, long count); #define strlen_user(str) strnlen_user(str, 32767) -extern unsigned long search_exception_table(unsigned long addr); - #endif /* _ASM_UACCESS_H */ diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h index 81e03530ed39..1ccf45657472 100644 --- a/arch/frv/include/uapi/asm/socket.h +++ b/arch/frv/include/uapi/asm/socket.h @@ -92,5 +92,11 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index ce29991e4219..fb08ebe0dab4 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c @@ -360,13 +360,8 @@ asmlinkage void memory_access_exception(unsigned long esr0, siginfo_t info; #ifdef CONFIG_MMU - unsigned long fixup; - - fixup = search_exception_table(__frame->pc); - if (fixup) { - __frame->pc = fixup; + if (fixup_exception(__frame)) return; - } #endif die_if_kernel("-- Memory Access Exception --\n" diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index aa6e573d57da..3f44dcbbad4d 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -102,6 +102,8 @@ SECTIONS _edata = .; /* End of data section */ + BUG_TABLE + /* GP section */ . = ALIGN(L1_CACHE_BYTES); _gp = . + 2048; diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c index a0e8b3e03e4c..9198ddd16092 100644 --- a/arch/frv/mm/extable.c +++ b/arch/frv/mm/extable.c @@ -10,40 +10,39 @@ extern const void __memset_end, __memset_user_error_lr, __memset_user_error_hand extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler; extern spinlock_t modlist_lock; - -/*****************************************************************************/ -/* - * see if there's a fixup handler available to deal with a kernel fault - */ -unsigned long search_exception_table(unsigned long pc) +int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *extab; + unsigned long pc = regs->pc; /* determine if the fault lay during a memcpy_user or a memset_user */ - if (__frame->lr == (unsigned long) &__memset_user_error_lr && + if (regs->lr == (unsigned long) &__memset_user_error_lr && (unsigned long) &memset <= pc && pc < (unsigned long) &__memset_end ) { /* the fault occurred in a protected memset * - we search for the return address (in LR) instead of the program counter * - it was probably during a clear_user() */ - return (unsigned long) &__memset_user_error_handler; + regs->pc = (unsigned long) &__memset_user_error_handler; + return 1; } - if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && + if (regs->lr == (unsigned long) &__memcpy_user_error_lr && (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end ) { /* the fault occurred in a protected memset * - we search for the return address (in LR) instead of the program counter * - it was probably during a copy_to/from_user() */ - return (unsigned long) &__memcpy_user_error_handler; + regs->pc = (unsigned long) &__memcpy_user_error_handler; + return 1; } extab = search_exception_tables(pc); - if (extab) - return extab->fixup; + if (extab) { + regs->pc = extab->fixup; + return 1; + } return 0; - -} /* end search_exception_table() */ +} diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 614a46c413d2..179e79e220e5 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c @@ -33,7 +33,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear { struct vm_area_struct *vma; struct mm_struct *mm; - unsigned long _pme, lrai, lrad, fixup; + unsigned long _pme, lrai, lrad; unsigned long flags = 0; siginfo_t info; pgd_t *pge; @@ -201,10 +201,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear no_context: /* are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(__frame->pc)) != 0) { - __frame->pc = fixup; + if (fixup_exception(__frame)) return; - } /* * Oops. The kernel tried to access some bad page. We'll have to diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index 341740c3581c..757cdeb24e6e 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild @@ -13,6 +13,7 @@ generic-y += dma.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += ftrace.h @@ -68,7 +69,6 @@ generic-y += tlbflush.h generic-y += trace_clock.h generic-y += topology.h generic-y += types.h -generic-y += uaccess.h generic-y += ucontext.h generic-y += unaligned.h generic-y += vga.h diff --git a/arch/h8300/include/asm/pgtable.h b/arch/h8300/include/asm/pgtable.h index 8341db67821d..7d265d28ba5e 100644 --- a/arch/h8300/include/asm/pgtable.h +++ b/arch/h8300/include/asm/pgtable.h @@ -1,5 +1,6 @@ #ifndef _H8300_PGTABLE_H #define _H8300_PGTABLE_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> #include <asm-generic/pgtable.h> #define pgtable_cache_init() do { } while (0) diff --git a/arch/h8300/include/asm/uaccess.h b/arch/h8300/include/asm/uaccess.h new file mode 100644 index 000000000000..6f6144a240ce --- /dev/null +++ b/arch/h8300/include/asm/uaccess.h @@ -0,0 +1,54 @@ +#ifndef _ASM_UACCESS_H +#define _ASM_UACCESS_H + +#include <linux/string.h> + +static inline __must_check unsigned long +raw_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; + } + } + + memcpy(to, (const void __force *)from, n); + return 0; +} + +static inline __must_check unsigned long +raw_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; + default: + break; + } + } + + memcpy((void __force *)to, from, n); + return 0; +} +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER + +#include <asm-generic/uaccess.h> + +#endif diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index 92075544a19a..0dc1c8f622bc 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -95,7 +95,8 @@ static int regs_get(struct task_struct *target, long *reg = (long *)®s; /* build user regs in buffer */ - for (r = 0; r < ARRAY_SIZE(register_offset); r++) + BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0); + for (r = 0; r < sizeof(regs) / sizeof(long); r++) *reg++ = h8300_get_reg(target, r); return user_regset_copyout(&pos, &count, &kbuf, &ubuf, @@ -113,7 +114,8 @@ static int regs_set(struct task_struct *target, long *reg; /* build user regs in buffer */ - for (reg = (long *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++) + BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0); + for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++) *reg++ = h8300_get_reg(target, r); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, @@ -122,7 +124,7 @@ static int regs_set(struct task_struct *target, return ret; /* write back to pt_regs */ - for (reg = (long *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++) + for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++) h8300_put_reg(target, r, *reg++); return 0; } diff --git a/arch/h8300/kernel/ptrace_h.c b/arch/h8300/kernel/ptrace_h.c index fe3b5673baba..f5ff3b794c85 100644 --- a/arch/h8300/kernel/ptrace_h.c +++ b/arch/h8300/kernel/ptrace_h.c @@ -9,7 +9,7 @@ */ #include <linux/linkage.h> -#include <linux/sched.h> +#include <linux/sched/signal.h> #include <asm/ptrace.h> #define BREAKINST 0x5730 /* trapa #3 */ diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index 797b64a4b80b..a2036bfda8af 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -11,6 +11,7 @@ generic-y += device.h generic-y += div64.h generic-y += emergency-restart.h generic-y += errno.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += ftrace.h diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h index 49eab8136ec3..24a9177fb897 100644 --- a/arch/hexagon/include/asm/pgtable.h +++ b/arch/hexagon/include/asm/pgtable.h @@ -26,6 +26,7 @@ */ #include <linux/swap.h> #include <asm/page.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> /* A handy thing to have if one has the RAM. Declared in head.S */ diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h index f61cfb28e9f2..458b69886b34 100644 --- a/arch/hexagon/include/asm/uaccess.h +++ b/arch/hexagon/include/asm/uaccess.h @@ -23,7 +23,6 @@ /* * User space memory access functions */ -#include <linux/sched.h> #include <linux/mm.h> #include <asm/segment.h> #include <asm/sections.h> @@ -50,8 +49,6 @@ * reasonably simple and not *too* slow. After all, we've got the * MMU for backup. */ -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 #define __access_ok(addr, size) \ ((get_fs().seg == KERNEL_DS.seg) || \ @@ -68,19 +65,12 @@ */ /* Assembly somewhat optimized copy routines */ -unsigned long __copy_from_user_hexagon(void *to, const void __user *from, +unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n); -unsigned long __copy_to_user_hexagon(void __user *to, const void *from, +unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n); - -#define __copy_from_user(to, from, n) __copy_from_user_hexagon(to, from, n) -#define __copy_to_user(to, from, n) __copy_to_user_hexagon(to, from, n) - -/* - * XXX todo: some additonal performance gain is possible by - * implementing __copy_to/from_user_inatomic, which is much - * like __copy_to/from_user, but performs slightly less checking. - */ +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER __kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count); #define __clear_user(a, s) __clear_user_hexagon((a), (s)) @@ -107,10 +97,14 @@ static inline long hexagon_strncpy_from_user(char *dst, const char __user *src, return -EFAULT; if (res > n) { - copy_from_user(dst, src, n); + long left = raw_copy_from_user(dst, src, n); + if (unlikely(left)) + memset(dst + (n - left), 0, left); return n; } else { - copy_from_user(dst, src, res); + long left = raw_copy_from_user(dst, src, res); + if (unlikely(left)) + memset(dst + (res - left), 0, left); return res-1; } } diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c index af9dec4c28eb..00bcad9cbd8f 100644 --- a/arch/hexagon/kernel/hexagon_ksyms.c +++ b/arch/hexagon/kernel/hexagon_ksyms.c @@ -25,8 +25,8 @@ /* Additional functions */ EXPORT_SYMBOL(__clear_user_hexagon); -EXPORT_SYMBOL(__copy_from_user_hexagon); -EXPORT_SYMBOL(__copy_to_user_hexagon); +EXPORT_SYMBOL(raw_copy_from_user); +EXPORT_SYMBOL(raw_copy_to_user); EXPORT_SYMBOL(__iounmap); EXPORT_SYMBOL(__strnlen_user); EXPORT_SYMBOL(__vmgetie); diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c index ff4e9bf995e9..29b1f57116c8 100644 --- a/arch/hexagon/kernel/time.c +++ b/arch/hexagon/kernel/time.c @@ -199,7 +199,9 @@ void __init time_init_deferred(void) clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4); ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev); + ce_dev->max_delta_ticks = 0x7fffffff; ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev); + ce_dev->min_delta_ticks = 0xf; #ifdef CONFIG_SMP setup_percpu_clockdev(); diff --git a/arch/hexagon/mm/copy_from_user.S b/arch/hexagon/mm/copy_from_user.S index 7fc94f3e6642..7da066fbd16f 100644 --- a/arch/hexagon/mm/copy_from_user.S +++ b/arch/hexagon/mm/copy_from_user.S @@ -44,7 +44,7 @@ #define bytes r2 #define loopcount r5 -#define FUNCNAME __copy_from_user_hexagon +#define FUNCNAME raw_copy_from_user #include "copy_user_template.S" /* LOAD FAULTS from COPY_FROM_USER */ diff --git a/arch/hexagon/mm/copy_to_user.S b/arch/hexagon/mm/copy_to_user.S index 0cfbcc09d1d9..a7b7f8db21df 100644 --- a/arch/hexagon/mm/copy_to_user.S +++ b/arch/hexagon/mm/copy_to_user.S @@ -43,7 +43,7 @@ #define bytes r2 #define loopcount r5 -#define FUNCNAME __copy_to_user_hexagon +#define FUNCNAME raw_copy_to_user #include "copy_user_template.S" /* STORE FAULTS from COPY_TO_USER */ diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 18ca6a9ce566..6a15083cc366 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -52,7 +52,6 @@ config IA64 select MODULES_USE_ELF_RELA select ARCH_USE_CMPXCHG_LOCKREF select HAVE_ARCH_AUDITSYSCALL - select HAVE_ARCH_HARDENED_USERCOPY default y help The Itanium Processor Family is Intel's 64-bit successor to diff --git a/arch/ia64/include/asm/asm-prototypes.h b/arch/ia64/include/asm/asm-prototypes.h new file mode 100644 index 000000000000..a2c139808cfe --- /dev/null +++ b/arch/ia64/include/asm/asm-prototypes.h @@ -0,0 +1,29 @@ +#ifndef _ASM_IA64_ASM_PROTOTYPES_H +#define _ASM_IA64_ASM_PROTOTYPES_H + +#include <asm/cacheflush.h> +#include <asm/checksum.h> +#include <asm/esi.h> +#include <asm/ftrace.h> +#include <asm/page.h> +#include <asm/pal.h> +#include <asm/string.h> +#include <asm/uaccess.h> +#include <asm/unwind.h> +#include <asm/xor.h> + +extern const char ia64_ivt[]; + +signed int __divsi3(signed int, unsigned int); +signed int __modsi3(signed int, unsigned int); + +signed long long __divdi3(signed long long, unsigned long long); +signed long long __moddi3(signed long long, unsigned long long); + +unsigned int __udivsi3(unsigned int, unsigned int); +unsigned int __umodsi3(unsigned int, unsigned int); + +unsigned long long __udivdi3(unsigned long long, unsigned long long); +unsigned long long __umoddi3(unsigned long long, unsigned long long); + +#endif /* _ASM_IA64_ASM_PROTOTYPES_H */ diff --git a/arch/ia64/include/asm/extable.h b/arch/ia64/include/asm/extable.h new file mode 100644 index 000000000000..20376e71eab4 --- /dev/null +++ b/arch/ia64/include/asm/extable.h @@ -0,0 +1,11 @@ +#ifndef _ASM_IA64_EXTABLE_H +#define _ASM_IA64_EXTABLE_H + +#define ARCH_HAS_RELATIVE_EXTABLE + +struct exception_table_entry { + int insn; /* location-relative address of insn this fixup is for */ + int fixup; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */ +}; + +#endif diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h index 384794e665fc..6cc22c8d8923 100644 --- a/arch/ia64/include/asm/pgtable.h +++ b/arch/ia64/include/asm/pgtable.h @@ -587,8 +587,10 @@ extern struct page *zero_page_memmap_ptr; #if CONFIG_PGTABLE_LEVELS == 3 +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> #endif +#include <asm-generic/5level-fixup.h> #include <asm-generic/pgtable.h> #endif /* _ASM_IA64_PGTABLE_H */ diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h index 471044be2a3b..82a7646c4416 100644 --- a/arch/ia64/include/asm/uaccess.h +++ b/arch/ia64/include/asm/uaccess.h @@ -33,14 +33,13 @@ */ #include <linux/compiler.h> -#include <linux/errno.h> -#include <linux/sched.h> #include <linux/page-flags.h> #include <linux/mm.h> #include <asm/intrinsics.h> #include <asm/pgtable.h> #include <asm/io.h> +#include <asm/extable.h> /* * For historical reasons, the following macros are grossly misnamed: @@ -48,9 +47,6 @@ #define KERNEL_DS ((mm_segment_t) { ~0UL }) /* cf. access_ok() */ #define USER_DS ((mm_segment_t) { TASK_SIZE-1 }) /* cf. access_ok() */ -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) #define set_fs(x) (current_thread_info()->addr_limit = (x)) @@ -63,14 +59,14 @@ * address TASK_SIZE is never valid. We also need to make sure that the address doesn't * point inside the virtually mapped linear page table. */ -#define __access_ok(addr, size, segment) \ -({ \ - __chk_user_ptr(addr); \ - (likely((unsigned long) (addr) <= (segment).seg) \ - && ((segment).seg == KERNEL_DS.seg \ - || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))); \ -}) -#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs()) +static inline int __access_ok(const void __user *p, unsigned long size) +{ + unsigned long addr = (unsigned long)p; + unsigned long seg = get_fs().seg; + return likely(addr <= seg) && + (seg == KERNEL_DS.seg || likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT)); +} +#define access_ok(type, addr, size) __access_ok((addr), (size)) /* * These are the main single-value transfer routines. They automatically @@ -80,8 +76,8 @@ * (a) re-use the arguments for side effects (sizeof/typeof is ok) * (b) require any knowledge of processes at this stage */ -#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)), get_fs()) -#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)), get_fs()) +#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr))) +#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr))) /* * The "__xxx" versions do not do address space checking, useful when @@ -184,13 +180,13 @@ extern void __get_user_unknown (void); * could clobber r8 and r9 (among others). Thus, be careful not to evaluate it while * using r8/r9. */ -#define __do_get_user(check, x, ptr, size, segment) \ +#define __do_get_user(check, x, ptr, size) \ ({ \ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ __typeof__ (size) __gu_size = (size); \ long __gu_err = -EFAULT; \ unsigned long __gu_val = 0; \ - if (!check || __access_ok(__gu_ptr, size, segment)) \ + if (!check || __access_ok(__gu_ptr, size)) \ switch (__gu_size) { \ case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \ case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break; \ @@ -202,8 +198,8 @@ extern void __get_user_unknown (void); __gu_err; \ }) -#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size, KERNEL_DS) -#define __get_user_check(x, ptr, size, segment) __do_get_user(1, x, ptr, size, segment) +#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size) +#define __get_user_check(x, ptr, size) __do_get_user(1, x, ptr, size) extern void __put_user_unknown (void); @@ -211,14 +207,14 @@ extern void __put_user_unknown (void); * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which * could clobber r8 (among others). Thus, be careful not to evaluate them while using r8. */ -#define __do_put_user(check, x, ptr, size, segment) \ +#define __do_put_user(check, x, ptr, size) \ ({ \ __typeof__ (x) __pu_x = (x); \ __typeof__ (*(ptr)) __user *__pu_ptr = (ptr); \ __typeof__ (size) __pu_size = (size); \ long __pu_err = -EFAULT; \ \ - if (!check || __access_ok(__pu_ptr, __pu_size, segment)) \ + if (!check || __access_ok(__pu_ptr, __pu_size)) \ switch (__pu_size) { \ case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break; \ case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break; \ @@ -229,8 +225,8 @@ extern void __put_user_unknown (void); __pu_err; \ }) -#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size, KERNEL_DS) -#define __put_user_check(x, ptr, size, segment) __do_put_user(1, x, ptr, size, segment) +#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size) +#define __put_user_check(x, ptr, size) __do_put_user(1, x, ptr, size) /* * Complex access routines @@ -239,56 +235,19 @@ extern unsigned long __must_check __copy_user (void __user *to, const void __use unsigned long count); static inline unsigned long -__copy_to_user (void __user *to, const void *from, unsigned long count) +raw_copy_to_user(void __user *to, const void *from, unsigned long count) { - check_object_size(from, count, true); - return __copy_user(to, (__force void __user *) from, count); } static inline unsigned long -__copy_from_user (void *to, const void __user *from, unsigned long count) +raw_copy_from_user(void *to, const void __user *from, unsigned long count) { - check_object_size(to, count, false); - return __copy_user((__force void __user *) to, from, count); } -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user -#define copy_to_user(to, from, n) \ -({ \ - void __user *__cu_to = (to); \ - const void *__cu_from = (from); \ - long __cu_len = (n); \ - \ - if (__access_ok(__cu_to, __cu_len, get_fs())) { \ - check_object_size(__cu_from, __cu_len, true); \ - __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \ - } \ - __cu_len; \ -}) - -static inline unsigned long -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - check_object_size(to, n, false); - if (likely(__access_ok(from, n, get_fs()))) - n = __copy_user((__force void __user *) to, from, n); - else - memset(to, 0, n); - return n; -} - -#define __copy_in_user(to, from, size) __copy_user((to), (from), (size)) - -static inline unsigned long -copy_in_user (void __user *to, const void __user *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))) - n = __copy_user(to, from, n); - return n; -} +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER extern unsigned long __do_clear_user (void __user *, unsigned long); @@ -297,7 +256,7 @@ extern unsigned long __do_clear_user (void __user *, unsigned long); #define clear_user(to, n) \ ({ \ unsigned long __cu_len = (n); \ - if (__access_ok(to, __cu_len, get_fs())) \ + if (__access_ok(to, __cu_len)) \ __cu_len = __do_clear_user(to, __cu_len); \ __cu_len; \ }) @@ -313,7 +272,7 @@ extern long __must_check __strncpy_from_user (char *to, const char __user *from, ({ \ const char __user * __sfu_from = (from); \ long __sfu_ret = -EFAULT; \ - if (__access_ok(__sfu_from, 0, get_fs())) \ + if (__access_ok(__sfu_from, 0)) \ __sfu_ret = __strncpy_from_user((to), __sfu_from, (n)); \ __sfu_ret; \ }) @@ -325,7 +284,7 @@ extern unsigned long __strlen_user (const char __user *); ({ \ const char __user *__su_str = (str); \ unsigned long __su_ret = 0; \ - if (__access_ok(__su_str, 0, get_fs())) \ + if (__access_ok(__su_str, 0)) \ __su_ret = __strlen_user(__su_str); \ __su_ret; \ }) @@ -341,18 +300,11 @@ extern unsigned long __strnlen_user (const char __user *, long); ({ \ const char __user *__su_str = (str); \ unsigned long __su_ret = 0; \ - if (__access_ok(__su_str, 0, get_fs())) \ + if (__access_ok(__su_str, 0)) \ __su_ret = __strnlen_user(__su_str, len); \ __su_ret; \ }) -#define ARCH_HAS_RELATIVE_EXTABLE - -struct exception_table_entry { - int insn; /* location-relative address of insn this fixup is for */ - int fixup; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */ -}; - #define ARCH_HAS_TRANSLATE_MEM_PTR 1 static __inline__ void * xlate_dev_mem_ptr(phys_addr_t p) diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h index 57feb0c1f7d7..2c3f4b48042a 100644 --- a/arch/ia64/include/uapi/asm/socket.h +++ b/arch/ia64/include/uapi/asm/socket.h @@ -101,4 +101,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _ASM_IA64_SOCKET_H */ diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 6ab0ae7d6535..d1d945c6bd05 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -153,7 +153,7 @@ slot (const struct insn *insn) static int apply_imm64 (struct module *mod, struct insn *insn, uint64_t val) { - if (slot(insn) != 2) { + if (slot(insn) != 1 && slot(insn) != 2) { printk(KERN_ERR "%s: invalid slot number %d for IMM64\n", mod->name, slot(insn)); return 0; @@ -165,7 +165,7 @@ apply_imm64 (struct module *mod, struct insn *insn, uint64_t val) static int apply_imm60 (struct module *mod, struct insn *insn, uint64_t val) { - if (slot(insn) != 2) { + if (slot(insn) != 1 && slot(insn) != 2) { printk(KERN_ERR "%s: invalid slot number %d for IMM60\n", mod->name, slot(insn)); return 0; diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index d194d5c83d32..63dc9cdc95c5 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -179,14 +179,14 @@ struct salinfo_platform_oemdata_parms { const u8 *efi_guid; u8 **oemdata; u64 *oemdata_size; - int ret; }; -static void +static long salinfo_platform_oemdata_cpu(void *context) { struct salinfo_platform_oemdata_parms *parms = context; - parms->ret = salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size); + + return salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size); } static void @@ -380,16 +380,7 @@ salinfo_log_release(struct inode *inode, struct file *file) return 0; } -static void -call_on_cpu(int cpu, void (*fn)(void *), void *arg) -{ - cpumask_t save_cpus_allowed = current->cpus_allowed; - set_cpus_allowed_ptr(current, cpumask_of(cpu)); - (*fn)(arg); - set_cpus_allowed_ptr(current, &save_cpus_allowed); -} - -static void +static long salinfo_log_read_cpu(void *context) { struct salinfo_data *data = context; @@ -399,6 +390,7 @@ salinfo_log_read_cpu(void *context) /* Clear corrected errors as they are read from SAL */ if (rh->severity == sal_log_severity_corrected) ia64_sal_clear_state_info(data->type); + return 0; } static void @@ -430,7 +422,7 @@ retry: spin_unlock_irqrestore(&data_saved_lock, flags); if (!data->saved_num) - call_on_cpu(cpu, salinfo_log_read_cpu, data); + work_on_cpu_safe(cpu, salinfo_log_read_cpu, data); if (!data->log_size) { data->state = STATE_NO_DATA; cpumask_clear_cpu(cpu, &data->cpu_event); @@ -459,11 +451,13 @@ salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *p return simple_read_from_buffer(buffer, count, ppos, buf, bufsize); } -static void +static long salinfo_log_clear_cpu(void *context) { struct salinfo_data *data = context; + ia64_sal_clear_state_info(data->type); + return 0; } static int @@ -486,7 +480,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu) rh = (sal_log_record_header_t *)(data->log_buffer); /* Corrected errors have already been cleared from SAL */ if (rh->severity != sal_log_severity_corrected) - call_on_cpu(cpu, salinfo_log_clear_cpu, data); + work_on_cpu_safe(cpu, salinfo_log_clear_cpu, data); /* clearing a record may make a new record visible */ salinfo_log_new_read(cpu, data); if (data->state == STATE_LOG_RECORD) { @@ -531,9 +525,8 @@ salinfo_log_write(struct file *file, const char __user *buffer, size_t count, lo .oemdata = &data->oemdata, .oemdata_size = &data->oemdata_size }; - call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms); - if (parms.ret) - count = parms.ret; + count = work_on_cpu_safe(cpu, salinfo_platform_oemdata_cpu, + &parms); } else data->oemdata_size = 0; } else diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 1a68f012a6dc..d76529cbff20 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -355,18 +355,12 @@ static int cache_add_dev(unsigned int cpu) unsigned long i, j; struct cache_info *this_object; int retval = 0; - cpumask_t oldmask; if (all_cpu_cache_info[cpu].kobj.parent) return 0; - oldmask = current->cpus_allowed; - retval = set_cpus_allowed_ptr(current, cpumask_of(cpu)); - if (unlikely(retval)) - return retval; retval = cpu_cache_sysfs_init(cpu); - set_cpus_allowed_ptr(current, &oldmask); if (unlikely(retval < 0)) return retval; diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index f89d20c97412..798026dde52e 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -192,6 +192,8 @@ SECTIONS { CONSTRUCTORS } + BUG_TABLE + . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */ .got : AT(ADDR(.got) - LOAD_OFFSET) { *(.got.plt) diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile index 1f3d3877618f..0a40b14407b1 100644 --- a/arch/ia64/lib/Makefile +++ b/arch/ia64/lib/Makefile @@ -24,25 +24,25 @@ AFLAGS___modsi3.o = -DMODULO AFLAGS___umodsi3.o = -DUNSIGNED -DMODULO $(obj)/__divdi3.o: $(src)/idiv64.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__udivdi3.o: $(src)/idiv64.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__moddi3.o: $(src)/idiv64.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__umoddi3.o: $(src)/idiv64.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__divsi3.o: $(src)/idiv32.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__udivsi3.o: $(src)/idiv32.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__modsi3.o: $(src)/idiv32.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) $(obj)/__umodsi3.o: $(src)/idiv32.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S index b264b6a7967b..bbbadc478f5b 100644 --- a/arch/ia64/lib/memcpy_mck.S +++ b/arch/ia64/lib/memcpy_mck.S @@ -556,9 +556,6 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \ #define D r22 #define F r28 -#define memset_arg0 r32 -#define memset_arg2 r33 - #define saved_retval loc0 #define saved_rtlink loc1 #define saved_pfs_stack loc2 @@ -622,7 +619,7 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \ * (faulting_addr - orig_dst) -> len to faulting st address * B = (cur_dst - orig_dst) -> len copied so far * C = A - B -> len need to be copied - * D = orig_len - A -> len need to be zeroed + * D = orig_len - A -> len need to be left along */ (p6) sub A = F, saved_in0 (p7) sub A = F, saved_in1 @@ -638,9 +635,6 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \ sub D = saved_in2, A ;; cmp.gt p8,p0=C,r0 // more than 1 byte? - add memset_arg0=saved_in0, A -(p6) mov memset_arg2=0 // copy_to_user should not call memset -(p7) mov memset_arg2=D // copy_from_user need to have kbuf zeroed mov r8=0 mov saved_retval = D mov saved_rtlink = b0 @@ -652,11 +646,6 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \ ;; add saved_retval=saved_retval,r8 // above might return non-zero value - cmp.gt p8,p0=memset_arg2,r0 // more than 1 byte? - mov out0=memset_arg0 // *s - mov out1=r0 // c - mov out2=memset_arg2 // n -(p8) br.call.sptk.few b0=memset ;; mov retval=saved_retval diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index 4edb816aba9a..10dd4a66e167 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c @@ -5,7 +5,10 @@ * David Mosberger-Tang <davidm@hpl.hp.com> */ -#include <linux/uaccess.h> +#include <asm/ptrace.h> +#include <asm/extable.h> +#include <asm/errno.h> +#include <asm/processor.h> void ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e) diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 52704f199dd6..55febd65911a 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -598,12 +598,17 @@ static void sn_hwperf_call_sal(void *info) op_info->ret = r; } +static long sn_hwperf_call_sal_work(void *info) +{ + sn_hwperf_call_sal(info); + return 0; +} + static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info) { u32 cpu; u32 use_ipi; int r = 0; - cpumask_t save_allowed; cpu = (op_info->a->arg & SN_HWPERF_ARG_CPU_MASK) >> 32; use_ipi = op_info->a->arg & SN_HWPERF_ARG_USE_IPI_MASK; @@ -629,13 +634,9 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info) /* use an interprocessor interrupt to call SAL */ smp_call_function_single(cpu, sn_hwperf_call_sal, op_info, 1); - } - else { - /* migrate the task before calling SAL */ - save_allowed = current->cpus_allowed; - set_cpus_allowed_ptr(current, cpumask_of(cpu)); - sn_hwperf_call_sal(op_info); - set_cpus_allowed_ptr(current, &save_allowed); + } else { + /* Call on the target CPU */ + work_on_cpu_safe(cpu, sn_hwperf_call_sal_work, op_info); } } r = op_info->ret; diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index deb298777df2..c000ffac8586 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@ -2,6 +2,7 @@ generic-y += clkdev.h generic-y += current.h generic-y += exec.h +generic-y += extable.h generic-y += irq_work.h generic-y += kvm_para.h generic-y += mcs_spinlock.h diff --git a/arch/m32r/include/asm/uaccess.h b/arch/m32r/include/asm/uaccess.h index 6f8982157a75..07be349c00ad 100644 --- a/arch/m32r/include/asm/uaccess.h +++ b/arch/m32r/include/asm/uaccess.h @@ -11,13 +11,9 @@ /* * User space memory access functions */ -#include <linux/errno.h> -#include <linux/thread_info.h> #include <asm/page.h> #include <asm/setup.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 +#include <linux/prefetch.h> /* * The fs value determines whether argument validity checking should be @@ -114,25 +110,7 @@ static inline int access_ok(int type, const void *addr, unsigned long size) } #endif /* CONFIG_MMU */ -/* - * 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; -}; - -extern int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> /* * These are the main single-value transfer routines. They automatically @@ -483,174 +461,25 @@ do { \ : "r14", "memory"); \ } while (0) -#define __copy_user_zeroing(to, from, size) \ -do { \ - unsigned long __dst, __src, __c; \ - __asm__ __volatile__ ( \ - " mv r14, %0\n" \ - " or r14, %1\n" \ - " beq %0, %1, 9f\n" \ - " beqz %2, 9f\n" \ - " and3 r14, r14, #3\n" \ - " bnez r14, 2f\n" \ - " and3 %2, %2, #3\n" \ - " beqz %3, 2f\n" \ - " addi %0, #-4 ; word_copy \n" \ - " .fillinsn\n" \ - "0: ld r14, @%1+\n" \ - " addi %3, #-1\n" \ - " .fillinsn\n" \ - "1: st r14, @+%0\n" \ - " bnez %3, 0b\n" \ - " beqz %2, 9f\n" \ - " addi %0, #4\n" \ - " .fillinsn\n" \ - "2: ldb r14, @%1 ; byte_copy \n" \ - " .fillinsn\n" \ - "3: stb r14, @%0\n" \ - " addi %1, #1\n" \ - " addi %2, #-1\n" \ - " addi %0, #1\n" \ - " bnez %2, 2b\n" \ - " .fillinsn\n" \ - "9:\n" \ - ".section .fixup,\"ax\"\n" \ - " .balign 4\n" \ - "5: addi %3, #1\n" \ - " addi %1, #-4\n" \ - " .fillinsn\n" \ - "6: slli %3, #2\n" \ - " add %2, %3\n" \ - " addi %0, #4\n" \ - " .fillinsn\n" \ - "7: ldi r14, #0 ; store zero \n" \ - " .fillinsn\n" \ - "8: addi %2, #-1\n" \ - " stb r14, @%0 ; ACE? \n" \ - " addi %0, #1\n" \ - " bnez %2, 8b\n" \ - " seth r14, #high(9b)\n" \ - " or3 r14, r14, #low(9b)\n" \ - " jmp r14\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .balign 4\n" \ - " .long 0b,6b\n" \ - " .long 1b,5b\n" \ - " .long 2b,7b\n" \ - " .long 3b,7b\n" \ - ".previous\n" \ - : "=&r" (__dst), "=&r" (__src), "=&r" (size), \ - "=&r" (__c) \ - : "0" (to), "1" (from), "2" (size), "3" (size / 4) \ - : "r14", "memory"); \ -} while (0) - - /* We let the __ versions of copy_from/to_user inline, because they're often * used in fast paths and have only a small space overhead. */ -static inline unsigned long __generic_copy_from_user_nocheck(void *to, - const void __user *from, unsigned long n) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - __copy_user_zeroing(to, from, n); + prefetchw(to); + __copy_user(to, from, n); return n; } -static inline unsigned long __generic_copy_to_user_nocheck(void __user *to, - const void *from, unsigned long n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { + prefetch(from); __copy_user(to, from, n); return n; } -unsigned long __generic_copy_to_user(void __user *, const void *, unsigned long); -unsigned long __generic_copy_from_user(void *, const void __user *, unsigned long); - -/** - * __copy_to_user: - Copy a block of data into user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -#define __copy_to_user(to, from, n) \ - __generic_copy_to_user_nocheck((to), (from), (n)) - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -/** - * copy_to_user: - Copy a block of data into user space. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -#define copy_to_user(to, from, n) \ -({ \ - might_fault(); \ - __generic_copy_to_user((to), (from), (n)); \ -}) - -/** - * __copy_from_user: - Copy a block of data from user space, with less checking. * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -#define __copy_from_user(to, from, n) \ - __generic_copy_from_user_nocheck((to), (from), (n)) - -/** - * copy_from_user: - Copy a block of data from user space. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -#define copy_from_user(to, from, n) \ -({ \ - might_fault(); \ - __generic_copy_from_user((to), (from), (n)); \ -}) - long __must_check strncpy_from_user(char *dst, const char __user *src, long count); long __must_check __strncpy_from_user(char *dst, diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h index 5853f8e92c20..ae6548d29a18 100644 --- a/arch/m32r/include/uapi/asm/socket.h +++ b/arch/m32r/include/uapi/asm/socket.h @@ -92,4 +92,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _ASM_M32R_SOCKET_H */ diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c index d763f0bd2106..a4d43b5cc102 100644 --- a/arch/m32r/kernel/m32r_ksyms.c +++ b/arch/m32r/kernel/m32r_ksyms.c @@ -26,8 +26,6 @@ EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(clear_user); EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(__generic_copy_from_user); -EXPORT_SYMBOL(__generic_copy_to_user); EXPORT_SYMBOL(strnlen_user); #ifdef CONFIG_SMP diff --git a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c index fd03f2731f20..b3ef2c899f96 100644 --- a/arch/m32r/lib/usercopy.c +++ b/arch/m32r/lib/usercopy.c @@ -11,27 +11,6 @@ #include <linux/thread_info.h> #include <linux/uaccess.h> -unsigned long -__generic_copy_to_user(void __user *to, const void *from, unsigned long n) -{ - prefetch(from); - if (access_ok(VERIFY_WRITE, to, n)) - __copy_user(to,from,n); - return n; -} - -unsigned long -__generic_copy_from_user(void *to, const void __user *from, unsigned long n) -{ - prefetchw(to); - if (access_ok(VERIFY_READ, from, n)) - __copy_user_zeroing(to,from,n); - else - memset(to, 0, n); - return n; -} - - /* * Copy a null terminated string from userspace. */ diff --git a/arch/m68k/coldfire/pit.c b/arch/m68k/coldfire/pit.c index 175553d5b8ed..6c0878018b44 100644 --- a/arch/m68k/coldfire/pit.c +++ b/arch/m68k/coldfire/pit.c @@ -149,8 +149,10 @@ void hw_timer_init(irq_handler_t handler) cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32); cf_pit_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFF, &cf_pit_clockevent); + cf_pit_clockevent.max_delta_ticks = 0xFFFF; cf_pit_clockevent.min_delta_ns = clockevent_delta2ns(0x3f, &cf_pit_clockevent); + cf_pit_clockevent.min_delta_ticks = 0x3f; clockevents_register_device(&cf_pit_clockevent); setup_irq(MCF_IRQ_PIT1, &pit_irq); diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 048bf076f7df..531cb9eb3319 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -25,6 +25,7 @@ CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68020=y @@ -60,6 +61,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -71,6 +73,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -101,6 +104,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -298,6 +302,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -371,6 +377,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -383,6 +390,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_A2065=y CONFIG_ARIADNE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -404,7 +412,6 @@ CONFIG_ZORRO8390=y # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -564,6 +571,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -594,6 +603,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -605,6 +615,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -629,4 +640,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index d4de24963f5f..ca91d39555da 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -26,6 +26,7 @@ CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68020=y @@ -58,6 +59,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -69,6 +71,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -99,6 +102,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -296,6 +300,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -353,6 +359,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -362,6 +369,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -378,7 +386,6 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -523,6 +530,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -553,6 +562,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -564,6 +574,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -588,4 +599,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index fc0fd3f871f3..23a3d8a691e2 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -25,6 +25,7 @@ CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68020=y @@ -58,6 +59,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -69,6 +71,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -99,6 +102,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -296,6 +300,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -362,6 +368,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -372,6 +379,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_ATARILANCE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -389,7 +397,6 @@ CONFIG_NE2000=y # CONFIG_NET_VENDOR_SOLARFLARE is not set CONFIG_SMC91X=y # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -544,6 +551,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -574,6 +583,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -585,6 +595,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -609,4 +620,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 52e984a0aa69..95deb95140fe 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -25,6 +25,7 @@ CONFIG_UNIXWARE_DISKLABEL=y CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68040=y @@ -56,6 +57,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -67,6 +69,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -97,6 +100,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -294,6 +298,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -352,6 +358,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -361,6 +368,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -377,7 +385,6 @@ CONFIG_BVME6000_NET=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -515,6 +522,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -545,6 +554,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -556,6 +566,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -580,4 +591,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index aaeed4422cc9..afae6958db2d 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -26,6 +26,7 @@ CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68020=y @@ -58,6 +59,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -69,6 +71,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -99,6 +102,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -296,6 +300,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -353,6 +359,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -363,6 +370,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_HPLANCE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -379,7 +387,6 @@ CONFIG_HPLANCE=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -525,6 +532,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -555,6 +564,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -566,6 +576,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -590,4 +601,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 3bbc9b2f0dac..b010734729a7 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -25,6 +25,7 @@ CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68020=y @@ -57,6 +58,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -68,6 +70,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -98,6 +101,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -298,6 +302,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -369,6 +375,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -379,6 +386,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_MACMACE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -398,7 +406,6 @@ CONFIG_MAC8390=y # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -547,6 +554,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -577,6 +586,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -588,6 +598,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -612,4 +623,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 8f2c0decb2f8..0e414549b235 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -21,6 +21,7 @@ CONFIG_SOLARIS_X86_PARTITION=y CONFIG_UNIXWARE_DISKLABEL=y # CONFIG_EFI_PARTITION is not set CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68020=y @@ -67,6 +68,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -78,6 +80,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -108,6 +111,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -308,6 +312,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -402,6 +408,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -419,6 +426,7 @@ CONFIG_HPLANCE=y CONFIG_MVME147_NET=y CONFIG_SUN3LANCE=y CONFIG_MACMACE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -444,7 +452,6 @@ CONFIG_ZORRO8390=y # CONFIG_NET_VENDOR_SOLARFLARE is not set CONFIG_SMC91X=y # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PLIP=m @@ -627,6 +634,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -657,6 +666,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -668,6 +678,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -692,4 +703,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index c743dd22e96f..b2e687a0ec3d 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -25,6 +25,7 @@ CONFIG_UNIXWARE_DISKLABEL=y CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68030=y @@ -55,6 +56,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -66,6 +68,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -96,6 +99,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -293,6 +297,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -351,6 +357,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -361,6 +368,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_MVME147_NET=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -377,7 +385,6 @@ CONFIG_MVME147_NET=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -515,6 +522,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -545,6 +554,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -556,6 +566,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -580,4 +591,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 2ccaca858f05..cbd8ee24d1bc 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -25,6 +25,7 @@ CONFIG_UNIXWARE_DISKLABEL=y CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68040=y @@ -56,6 +57,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -67,6 +69,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -97,6 +100,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -294,6 +298,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -352,6 +358,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -361,6 +368,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -377,7 +385,6 @@ CONFIG_MVME16x_NET=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -515,6 +522,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -545,6 +554,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -556,6 +566,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -580,4 +591,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 5599f3fd5fcd..1e82cc944339 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -26,6 +26,7 @@ CONFIG_SUN_PARTITION=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_M68040=y @@ -56,6 +57,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -67,6 +69,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -97,6 +100,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -294,6 +298,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -358,6 +364,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -369,6 +376,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -388,7 +396,6 @@ CONFIG_NE2000=y # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PLIP=m @@ -538,6 +545,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -568,6 +577,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -579,6 +589,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -603,4 +614,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 313bf0a562ad..f9e77f57a972 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -25,6 +25,7 @@ CONFIG_UNIXWARE_DISKLABEL=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_SUN3=y @@ -53,6 +54,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -64,6 +66,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -94,6 +97,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -291,6 +295,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -349,6 +355,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -359,6 +366,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_SUN3LANCE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_EZCHIP is not set @@ -375,7 +383,6 @@ CONFIG_SUN3_82586=y # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set # CONFIG_NET_VENDOR_SUN is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -517,6 +524,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -546,6 +555,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -557,6 +567,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -581,4 +592,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 38b61365f769..3c394fcfb368 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -25,6 +25,7 @@ CONFIG_UNIXWARE_DISKLABEL=y # CONFIG_EFI_PARTITION is not set CONFIG_SYSV68_PARTITION=y CONFIG_IOSCHED_DEADLINE=m +CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_KEXEC=y CONFIG_BOOTINFO_PROC=y CONFIG_SUN3X=y @@ -53,6 +54,7 @@ CONFIG_NET_IPVTI=m CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m CONFIG_INET_IPCOMP=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m @@ -64,6 +66,7 @@ CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m @@ -94,6 +97,7 @@ CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m CONFIG_NFT_SET_RBTREE=m CONFIG_NFT_SET_HASH=m +CONFIG_NFT_SET_BITMAP=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m @@ -291,6 +295,8 @@ CONFIG_MPLS_IPTUNNEL=m CONFIG_NET_L3_MASTER_DEV=y CONFIG_AF_KCM=m # CONFIG_WIRELESS is not set +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m CONFIG_NET_DEVLINK=m # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y @@ -349,6 +355,7 @@ CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m +CONFIG_IPVTAP=m CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_GTP=m @@ -359,6 +366,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set CONFIG_SUN3LANCE=y +# CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -375,7 +383,6 @@ CONFIG_SUN3LANCE=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PPP=m @@ -517,6 +524,8 @@ CONFIG_NLS_MAC_TURKISH=m CONFIG_DLM=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_WW_MUTEX_SELFTEST=m +CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m CONFIG_TEST_HEXDUMP=m CONFIG_TEST_STRING_HELPERS=m @@ -547,6 +556,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_VMAC=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -558,6 +568,7 @@ CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m @@ -582,4 +593,5 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set +CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index d4f9ccbfa85c..82005d2ff717 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -5,6 +5,7 @@ generic-y += device.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += futex.h generic-y += hw_irq.h generic-y += ioctl.h diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h index b4a9b0d5928d..dda58cfe8c22 100644 --- a/arch/m68k/include/asm/bitops.h +++ b/arch/m68k/include/asm/bitops.h @@ -148,7 +148,7 @@ static inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr) #define __change_bit(nr, vaddr) change_bit(nr, vaddr) -static inline int test_bit(int nr, const unsigned long *vaddr) +static inline int test_bit(int nr, const volatile unsigned long *vaddr) { return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0; } diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h index f5f790c31bf8..77239e81379b 100644 --- a/arch/m68k/include/asm/processor.h +++ b/arch/m68k/include/asm/processor.h @@ -122,16 +122,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc, wrusp(usp); } -#ifdef CONFIG_MMU -extern int handle_kernel_fault(struct pt_regs *regs); -#else -static inline int handle_kernel_fault(struct pt_regs *regs) -{ - /* Any fault in kernel is fatal on non-mmu */ - return 0; -} -#endif - /* Forward declaration, a strange C thing */ struct task_struct; diff --git a/arch/m68k/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess.h index 3fadc4a93d97..67b3481d6020 100644 --- a/arch/m68k/include/asm/uaccess.h +++ b/arch/m68k/include/asm/uaccess.h @@ -4,6 +4,7 @@ #include <asm/uaccess_mm.h> #endif +#include <asm/extable.h> #ifdef CONFIG_CPU_HAS_NO_UNALIGNED #include <asm-generic/uaccess-unaligned.h> #else diff --git a/arch/m68k/include/asm/uaccess_mm.h b/arch/m68k/include/asm/uaccess_mm.h index d228601b3afc..ef856ffeffdf 100644 --- a/arch/m68k/include/asm/uaccess_mm.h +++ b/arch/m68k/include/asm/uaccess_mm.h @@ -5,14 +5,9 @@ * User space memory access functions */ #include <linux/compiler.h> -#include <linux/errno.h> #include <linux/types.h> -#include <linux/sched.h> #include <asm/segment.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - /* We let the MMU do all checking */ static inline int access_ok(int type, const void __user *addr, unsigned long size) @@ -36,24 +31,6 @@ static inline int access_ok(int type, const void __user *addr, #define MOVES "move" #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; -}; - extern int __put_user_bad(void); extern int __get_user_bad(void); @@ -202,39 +179,55 @@ asm volatile ("\n" \ unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n); unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n); -#define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\ +#define __suffix0 +#define __suffix1 b +#define __suffix2 w +#define __suffix4 l + +#define ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\ asm volatile ("\n" \ "1: "MOVES"."#s1" (%2)+,%3\n" \ " move."#s1" %3,(%1)+\n" \ + " .ifnc \""#s2"\",\"\"\n" \ "2: "MOVES"."#s2" (%2)+,%3\n" \ " move."#s2" %3,(%1)+\n" \ " .ifnc \""#s3"\",\"\"\n" \ "3: "MOVES"."#s3" (%2)+,%3\n" \ " move."#s3" %3,(%1)+\n" \ " .endif\n" \ + " .endif\n" \ "4:\n" \ " .section __ex_table,\"a\"\n" \ " .align 4\n" \ " .long 1b,10f\n" \ + " .ifnc \""#s2"\",\"\"\n" \ " .long 2b,20f\n" \ " .ifnc \""#s3"\",\"\"\n" \ " .long 3b,30f\n" \ " .endif\n" \ + " .endif\n" \ " .previous\n" \ "\n" \ " .section .fixup,\"ax\"\n" \ " .even\n" \ - "10: clr."#s1" (%1)+\n" \ - "20: clr."#s2" (%1)+\n" \ + "10: addq.l #"#n1",%0\n" \ + " .ifnc \""#s2"\",\"\"\n" \ + "20: addq.l #"#n2",%0\n" \ " .ifnc \""#s3"\",\"\"\n" \ - "30: clr."#s3" (%1)+\n" \ + "30: addq.l #"#n3",%0\n" \ + " .endif\n" \ " .endif\n" \ - " moveq.l #"#n",%0\n" \ " jra 4b\n" \ " .previous\n" \ : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \ : : "memory") +#define ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\ + ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3) +#define __constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3) \ + ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, \ + __suffix##n1, __suffix##n2, __suffix##n3) + static __always_inline unsigned long __constant_copy_from_user(void *to, const void __user *from, unsigned long n) { @@ -242,37 +235,37 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n) switch (n) { case 1: - __get_user_asm(res, *(u8 *)to, (u8 __user *)from, u8, b, d, 1); + __constant_copy_from_user_asm(res, to, from, tmp, 1, 0, 0); break; case 2: - __get_user_asm(res, *(u16 *)to, (u16 __user *)from, u16, w, r, 2); + __constant_copy_from_user_asm(res, to, from, tmp, 2, 0, 0); break; case 3: - __constant_copy_from_user_asm(res, to, from, tmp, 3, w, b,); + __constant_copy_from_user_asm(res, to, from, tmp, 2, 1, 0); break; case 4: - __get_user_asm(res, *(u32 *)to, (u32 __user *)from, u32, l, r, 4); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 0, 0); break; case 5: - __constant_copy_from_user_asm(res, to, from, tmp, 5, l, b,); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 1, 0); break; case 6: - __constant_copy_from_user_asm(res, to, from, tmp, 6, l, w,); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 0); break; case 7: - __constant_copy_from_user_asm(res, to, from, tmp, 7, l, w, b); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 1); break; case 8: - __constant_copy_from_user_asm(res, to, from, tmp, 8, l, l,); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 0); break; case 9: - __constant_copy_from_user_asm(res, to, from, tmp, 9, l, l, b); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 1); break; case 10: - __constant_copy_from_user_asm(res, to, from, tmp, 10, l, l, w); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 2); break; case 12: - __constant_copy_from_user_asm(res, to, from, tmp, 12, l, l, l); + __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 4); break; default: /* we limit the inlined version to 3 moves */ @@ -363,24 +356,26 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) return res; } -#define __copy_from_user(to, from, n) \ -(__builtin_constant_p(n) ? \ - __constant_copy_from_user(to, from, n) : \ - __generic_copy_from_user(to, from, n)) - -#define __copy_to_user(to, from, n) \ -(__builtin_constant_p(n) ? \ - __constant_copy_to_user(to, from, n) : \ - __generic_copy_to_user(to, from, n)) - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) +{ + if (__builtin_constant_p(n)) + return __constant_copy_from_user(to, from, n); + return __generic_copy_from_user(to, from, n); +} -#define copy_from_user(to, from, n) __copy_from_user(to, from, n) -#define copy_to_user(to, from, n) __copy_to_user(to, from, n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) +{ + if (__builtin_constant_p(n)) + return __constant_copy_to_user(to, from, n); + return __generic_copy_to_user(to, from, n); +} +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER #define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) + (uaccess_kernel() ? ~0UL : TASK_SIZE) extern long strncpy_from_user(char *dst, const char __user *src, long count); extern __must_check long strlen_user(const char __user *str); diff --git a/arch/m68k/include/asm/uaccess_no.h b/arch/m68k/include/asm/uaccess_no.h index 36deeb36503b..e482c3899ff1 100644 --- a/arch/m68k/include/asm/uaccess_no.h +++ b/arch/m68k/include/asm/uaccess_no.h @@ -4,15 +4,11 @@ /* * User space memory access functions */ -#include <linux/sched.h> #include <linux/mm.h> #include <linux/string.h> #include <asm/segment.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size)) /* @@ -27,25 +23,6 @@ static inline int _access_ok(unsigned long addr, unsigned long size) } /* - * 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; -}; - - -/* * These are the main single-value transfer routines. They automatically * use the right size if we just have the right pointer type. */ @@ -124,13 +101,21 @@ extern int __get_user_bad(void); : "=d" (x) \ : "m" (*__ptr(ptr))) -#define copy_from_user(to, from, n) (memcpy(to, from, n), 0) -#define copy_to_user(to, from, n) (memcpy(to, from, n), 0) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) +{ + memcpy(to, (__force const void *)from, n); + return 0; +} -#define __copy_from_user(to, from, n) copy_from_user(to, from, n) -#define __copy_to_user(to, from, n) copy_to_user(to, from, n) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) +{ + memcpy((__force void *)to, from, n); + return 0; +} +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * Copy a null terminated string from userspace. diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index a857d82ec509..aab1edd0d4ba 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -4,7 +4,7 @@ #include <uapi/asm/unistd.h> -#define NR_syscalls 379 +#define NR_syscalls 380 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h index 9fe674bf911f..25589f5b8669 100644 --- a/arch/m68k/include/uapi/asm/unistd.h +++ b/arch/m68k/include/uapi/asm/unistd.h @@ -384,5 +384,6 @@ #define __NR_copy_file_range 376 #define __NR_preadv2 377 #define __NR_pwritev2 378 +#define __NR_statx 379 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 093b7c42fb85..6f945bb5ffbd 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -88,7 +88,7 @@ static inline int frame_extra_sizes(int f) return frame_size_change[f]; } -int handle_kernel_fault(struct pt_regs *regs) +int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fixup; struct pt_regs *tregs; diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index d6fd6d9ced24..8c9fcfafe0dd 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -399,3 +399,4 @@ ENTRY(sys_call_table) .long sys_copy_file_range .long sys_preadv2 .long sys_pwritev2 + .long sys_statx diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index a926d2c88898..c1cc4e99aa94 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -1016,8 +1016,13 @@ asmlinkage void trap_c(struct frame *fp) /* traced a trapping instruction on a 68020/30, * real exception will be executed afterwards. */ - } else if (!handle_kernel_fault(&fp->ptregs)) - bad_super_trap(fp); + return; + } +#ifdef CONFIG_MMU + if (fixup_exception(&fp->ptregs)) + return; +#endif + bad_super_trap(fp); return; } diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c index a76b73abaf64..7646e461aa62 100644 --- a/arch/m68k/lib/uaccess.c +++ b/arch/m68k/lib/uaccess.c @@ -30,19 +30,13 @@ unsigned long __generic_copy_from_user(void *to, const void __user *from, "6:\n" " .section .fixup,\"ax\"\n" " .even\n" - "10: move.l %0,%3\n" - "7: clr.l (%2)+\n" - " subq.l #1,%3\n" - " jne 7b\n" - " lsl.l #2,%0\n" + "10: lsl.l #2,%0\n" " btst #1,%5\n" " jeq 8f\n" - "30: clr.w (%2)+\n" - " addq.l #2,%0\n" + "30: addq.l #2,%0\n" "8: btst #0,%5\n" " jeq 6b\n" - "50: clr.b (%2)+\n" - " addq.l #1,%0\n" + "50: addq.l #1,%0\n" " jra 6b\n" " .previous\n" "\n" diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 9dc65a4c28d2..22123f7e8f75 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -150,7 +150,7 @@ static void mac_cache_card_flush(int writeback) void __init config_mac(void) { if (!MACH_IS_MAC) - printk(KERN_ERR "ERROR: no Mac, but config_mac() called!!\n"); + pr_err("ERROR: no Mac, but config_mac() called!!\n"); mach_sched_init = mac_sched_init; mach_init_IRQ = mac_init_IRQ; @@ -837,8 +837,7 @@ static void __init mac_identify(void) /* no bootinfo model id -> NetBSD booter was used! */ /* XXX FIXME: breaks for model > 31 */ model = (mac_bi_data.cpuid >> 2) & 63; - printk(KERN_WARNING "No bootinfo model ID, using cpuid instead " - "(obsolete bootloader?)\n"); + pr_warn("No bootinfo model ID, using cpuid instead (obsolete bootloader?)\n"); } macintosh_config = mac_data_table; @@ -880,14 +879,13 @@ static void __init mac_identify(void) */ iop_preinit(); - printk(KERN_INFO "Detected Macintosh model: %d\n", model); + pr_info("Detected Macintosh model: %d\n", model); /* * Report booter data: */ printk(KERN_DEBUG " Penguin bootinfo data:\n"); - printk(KERN_DEBUG " Video: addr 0x%lx " - "row 0x%lx depth %lx dimensions %ld x %ld\n", + printk(KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n", mac_bi_data.videoaddr, mac_bi_data.videorow, mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, mac_bi_data.dimensions >> 16); @@ -912,7 +910,7 @@ static void __init mac_identify(void) static void __init mac_report_hardware(void) { - printk(KERN_INFO "Apple Macintosh %s\n", macintosh_config->name); + pr_info("Apple Macintosh %s\n", macintosh_config->name); } static void mac_get_model(char *str) @@ -921,15 +919,6 @@ static void mac_get_model(char *str) strcat(str, macintosh_config->name); } -static struct resource swim_rsrc = { .flags = IORESOURCE_MEM }; - -static struct platform_device swim_pdev = { - .name = "swim", - .id = -1, - .num_resources = 1, - .resource = &swim_rsrc, -}; - static const struct resource mac_scsi_iifx_rsrc[] __initconst = { { .flags = IORESOURCE_IRQ, @@ -994,26 +983,6 @@ static const struct resource mac_scsi_ccl_rsrc[] __initconst = { }, }; -static struct platform_device esp_0_pdev = { - .name = "mac_esp", - .id = 0, -}; - -static struct platform_device esp_1_pdev = { - .name = "mac_esp", - .id = 1, -}; - -static struct platform_device sonic_pdev = { - .name = "macsonic", - .id = -1, -}; - -static struct platform_device mace_pdev = { - .name = "macmace", - .id = -1, -}; - int __init mac_platform_init(void) { u8 *swim_base; @@ -1045,9 +1014,13 @@ int __init mac_platform_init(void) } if (swim_base) { - swim_rsrc.start = (resource_size_t) swim_base, - swim_rsrc.end = (resource_size_t) swim_base + 0x2000, - platform_device_register(&swim_pdev); + struct resource swim_rsrc = { + .flags = IORESOURCE_MEM, + .start = (resource_size_t)swim_base, + .end = (resource_size_t)swim_base + 0x2000, + }; + + platform_device_register_simple("swim", -1, &swim_rsrc, 1); } /* @@ -1057,13 +1030,13 @@ int __init mac_platform_init(void) switch (macintosh_config->scsi_type) { case MAC_SCSI_QUADRA: case MAC_SCSI_QUADRA3: - platform_device_register(&esp_0_pdev); + platform_device_register_simple("mac_esp", 0, NULL, 0); break; case MAC_SCSI_QUADRA2: - platform_device_register(&esp_0_pdev); + platform_device_register_simple("mac_esp", 0, NULL, 0); if ((macintosh_config->ident == MAC_MODEL_Q900) || (macintosh_config->ident == MAC_MODEL_Q950)) - platform_device_register(&esp_1_pdev); + platform_device_register_simple("mac_esp", 1, NULL, 0); break; case MAC_SCSI_IIFX: /* Addresses from The Guide to Mac Family Hardware. @@ -1129,10 +1102,10 @@ int __init mac_platform_init(void) switch (macintosh_config->ether_type) { case MAC_ETHER_SONIC: - platform_device_register(&sonic_pdev); + platform_device_register_simple("macsonic", -1, NULL, 0); break; case MAC_ETHER_MACE: - platform_device_register(&mace_pdev); + platform_device_register_simple("macmace", -1, NULL, 0); break; } diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 7990b6f50105..4c1e606e7d03 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -115,7 +115,17 @@ #include <asm/macints.h> #include <asm/mac_iop.h> -/*#define DEBUG_IOP*/ +#ifdef DEBUG +#define iop_pr_debug(fmt, ...) \ + printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__) +#define iop_pr_cont(fmt, ...) \ + printk(KERN_CONT fmt, ##__VA_ARGS__) +#else +#define iop_pr_debug(fmt, ...) \ + no_printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__) +#define iop_pr_cont(fmt, ...) \ + no_printk(KERN_CONT fmt, ##__VA_ARGS__) +#endif /* Non-zero if the IOPs are present */ @@ -200,7 +210,7 @@ static int iop_alive(volatile struct mac_iop *iop) return retval; } -static struct iop_msg *iop_alloc_msg(void) +static struct iop_msg *iop_get_unused_msg(void) { int i; unsigned long flags; @@ -219,11 +229,6 @@ static struct iop_msg *iop_alloc_msg(void) return NULL; } -static void iop_free_msg(struct iop_msg *msg) -{ - msg->status = IOP_MSGSTATUS_UNUSED; -} - /* * This is called by the startup code before anything else. Its purpose * is to find and initialize the IOPs early in the boot sequence, so that @@ -268,10 +273,10 @@ void __init iop_init(void) int i; if (iop_scc_present) { - printk("IOP: detected SCC IOP at %p\n", iop_base[IOP_NUM_SCC]); + pr_info("IOP: detected SCC IOP at %p\n", iop_base[IOP_NUM_SCC]); } if (iop_ism_present) { - printk("IOP: detected ISM IOP at %p\n", iop_base[IOP_NUM_ISM]); + pr_info("IOP: detected ISM IOP at %p\n", iop_base[IOP_NUM_ISM]); iop_start(iop_base[IOP_NUM_ISM]); iop_alive(iop_base[IOP_NUM_ISM]); /* clears the alive flag */ } @@ -310,9 +315,9 @@ void __init iop_register_interrupts(void) pr_err("Couldn't register ISM IOP interrupt\n"); } if (!iop_alive(iop_base[IOP_NUM_ISM])) { - printk("IOP: oh my god, they killed the ISM IOP!\n"); + pr_warn("IOP: oh my god, they killed the ISM IOP!\n"); } else { - printk("IOP: the ISM IOP seems to be alive.\n"); + pr_warn("IOP: the ISM IOP seems to be alive.\n"); } } } @@ -349,9 +354,8 @@ void iop_complete_message(struct iop_msg *msg) int chan = msg->channel; int i,offset; -#ifdef DEBUG_IOP - printk("iop_complete(%p): iop %d chan %d\n", msg, msg->iop_num, msg->channel); -#endif + iop_pr_debug("msg %p iop_num %d channel %d\n", msg, msg->iop_num, + msg->channel); offset = IOP_ADDR_RECV_MSG + (msg->channel * IOP_MSG_LEN); @@ -363,7 +367,7 @@ void iop_complete_message(struct iop_msg *msg) IOP_ADDR_RECV_STATE + chan, IOP_MSG_COMPLETE); iop_interrupt(iop_base[msg->iop_num]); - iop_free_msg(msg); + msg->status = IOP_MSGSTATUS_UNUSED; } /* @@ -394,12 +398,10 @@ static void iop_do_send(struct iop_msg *msg) static void iop_handle_send(uint iop_num, uint chan) { volatile struct mac_iop *iop = iop_base[iop_num]; - struct iop_msg *msg,*msg2; + struct iop_msg *msg; int i,offset; -#ifdef DEBUG_IOP - printk("iop_handle_send: iop %d channel %d\n", iop_num, chan); -#endif + iop_pr_debug("iop_num %d chan %d\n", iop_num, chan); iop_writeb(iop, IOP_ADDR_SEND_STATE + chan, IOP_MSG_IDLE); @@ -411,10 +413,8 @@ static void iop_handle_send(uint iop_num, uint chan) msg->reply[i] = iop_readb(iop, offset); } if (msg->handler) (*msg->handler)(msg); - msg2 = msg; + msg->status = IOP_MSGSTATUS_UNUSED; msg = msg->next; - iop_free_msg(msg2); - iop_send_queue[iop_num][chan] = msg; if (msg) iop_do_send(msg); } @@ -430,11 +430,9 @@ static void iop_handle_recv(uint iop_num, uint chan) int i,offset; struct iop_msg *msg; -#ifdef DEBUG_IOP - printk("iop_handle_recv: iop %d channel %d\n", iop_num, chan); -#endif + iop_pr_debug("iop_num %d chan %d\n", iop_num, chan); - msg = iop_alloc_msg(); + msg = iop_get_unused_msg(); msg->iop_num = iop_num; msg->channel = chan; msg->status = IOP_MSGSTATUS_UNSOL; @@ -454,14 +452,9 @@ static void iop_handle_recv(uint iop_num, uint chan) if (msg->handler) { (*msg->handler)(msg); } else { -#ifdef DEBUG_IOP - printk("iop_handle_recv: unclaimed message on iop %d channel %d\n", iop_num, chan); - printk("iop_handle_recv:"); - for (i = 0 ; i < IOP_MSG_LEN ; i++) { - printk(" %02X", (uint) msg->message[i]); - } - printk("\n"); -#endif + iop_pr_debug("unclaimed message on iop_num %d chan %d\n", + iop_num, chan); + iop_pr_debug("%*ph\n", IOP_MSG_LEN, msg->message); iop_complete_message(msg); } } @@ -484,7 +477,7 @@ int iop_send_message(uint iop_num, uint chan, void *privdata, if (chan >= NUM_IOP_CHAN) return -EINVAL; if (msg_len > IOP_MSG_LEN) return -EINVAL; - msg = iop_alloc_msg(); + msg = iop_get_unused_msg(); if (!msg) return -ENOMEM; msg->next = NULL; @@ -574,50 +567,34 @@ irqreturn_t iop_ism_irq(int irq, void *dev_id) volatile struct mac_iop *iop = iop_base[iop_num]; int i,state; -#ifdef DEBUG_IOP - printk("iop_ism_irq: status = %02X\n", (uint) iop->status_ctrl); -#endif + iop_pr_debug("status %02X\n", iop->status_ctrl); /* INT0 indicates a state change on an outgoing message channel */ if (iop->status_ctrl & IOP_INT0) { iop->status_ctrl = IOP_INT0 | IOP_RUN | IOP_AUTOINC; -#ifdef DEBUG_IOP - printk("iop_ism_irq: new status = %02X, send states", - (uint) iop->status_ctrl); -#endif + iop_pr_debug("new status %02X, send states", iop->status_ctrl); for (i = 0 ; i < NUM_IOP_CHAN ; i++) { state = iop_readb(iop, IOP_ADDR_SEND_STATE + i); -#ifdef DEBUG_IOP - printk(" %02X", state); -#endif + iop_pr_cont(" %02X", state); if (state == IOP_MSG_COMPLETE) { iop_handle_send(iop_num, i); } } -#ifdef DEBUG_IOP - printk("\n"); -#endif + iop_pr_cont("\n"); } if (iop->status_ctrl & IOP_INT1) { /* INT1 for incoming msgs */ iop->status_ctrl = IOP_INT1 | IOP_RUN | IOP_AUTOINC; -#ifdef DEBUG_IOP - printk("iop_ism_irq: new status = %02X, recv states", - (uint) iop->status_ctrl); -#endif + iop_pr_debug("new status %02X, recv states", iop->status_ctrl); for (i = 0 ; i < NUM_IOP_CHAN ; i++) { state = iop_readb(iop, IOP_ADDR_RECV_STATE + i); -#ifdef DEBUG_IOP - printk(" %02X", state); -#endif + iop_pr_cont(" %02X", state); if (state == IOP_MSG_NEW) { iop_handle_recv(iop_num, i); } } -#ifdef DEBUG_IOP - printk("\n"); -#endif + iop_pr_cont("\n"); } return IRQ_HANDLED; } diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 5b01704c85eb..8aa8792e3174 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -281,8 +281,7 @@ static long via_read_time(void) last_result.idata = result.idata; } - pr_err("via_read_time: failed to read a stable value; " - "got 0x%08lx then 0x%08lx\n", + pr_err("via_read_time: failed to read a stable value; got 0x%08lx then 0x%08lx\n", last_result.idata, result.idata); return 0; @@ -465,7 +464,7 @@ void mac_poweroff(void) #endif } local_irq_enable(); - printk("It is now safe to turn off your Macintosh.\n"); + pr_crit("It is now safe to turn off your Macintosh.\n"); while(1); } @@ -556,7 +555,7 @@ void mac_reset(void) /* should never get here */ local_irq_enable(); - printk ("Restart failed. Please restart manually.\n"); + pr_crit("Restart failed. Please restart manually.\n"); while(1); } @@ -661,17 +660,13 @@ int mac_hwclk(int op, struct rtc_time *t) unmktime(now, 0, &t->tm_year, &t->tm_mon, &t->tm_mday, &t->tm_hour, &t->tm_min, &t->tm_sec); -#if 0 - printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n", - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); -#endif + pr_debug("%s: read %04d-%02d-%-2d %02d:%02d:%02d\n", + __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); } else { /* write */ -#if 0 - printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n", - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); -#endif + pr_debug("%s: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n", + __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index bd66a0b20c6b..2795e4ca09d7 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -32,7 +32,7 @@ int send_fault_sig(struct pt_regs *regs) force_sig_info(siginfo.si_signo, &siginfo, current); } else { - if (handle_kernel_fault(regs)) + if (fixup_exception(regs)) return -1; //if (siginfo.si_signo == SIGBUS) diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild index f9b9df5d6de9..8f940553a579 100644 --- a/arch/metag/include/asm/Kbuild +++ b/arch/metag/include/asm/Kbuild @@ -8,6 +8,7 @@ generic-y += dma.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += futex.h diff --git a/arch/metag/include/asm/pgtable.h b/arch/metag/include/asm/pgtable.h index ffa3a3a2ecad..0c151e5af079 100644 --- a/arch/metag/include/asm/pgtable.h +++ b/arch/metag/include/asm/pgtable.h @@ -6,6 +6,7 @@ #define _METAG_PGTABLE_H #include <asm/pgtable-bits.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> /* Invalid regions on Meta: 0x00000000-0x001FFFFF and 0xFFFF0000-0xFFFFFFFF */ diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 273e61225c27..5ebc2850690e 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -4,10 +4,6 @@ /* * User space memory access functions */ -#include <linux/sched.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 /* * The fs value determines whether argument validity checking should be @@ -28,7 +24,7 @@ #define segment_eq(a, b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) +#define __kernel_ok (uaccess_kernel()) /* * Explicitly allow NULL pointers here. Parts of the kernel such * as readv/writev use access_ok to validate pointers, but want @@ -51,28 +47,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size) #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ (unsigned long)(size)) -static inline int verify_area(int type, const void *addr, unsigned long size) -{ - return access_ok(type, addr, size) ? 0 : -EFAULT; -} - -/* - * 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; -}; - -extern int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> /* * These are the main single-value transfer routines. They automatically @@ -197,36 +172,10 @@ extern long __must_check strnlen_user(const char __user *src, long count); #define strlen_user(str) strnlen_user(str, 32767) -extern unsigned long __must_check __copy_user_zeroing(void *to, - const void __user *from, - unsigned long n); - -static inline unsigned long -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_READ, from, n))) - return __copy_user_zeroing(to, from, n); - memset(to, 0, n); - return n; -} - -#define __copy_from_user(to, from, n) __copy_user_zeroing(to, from, n) -#define __copy_from_user_inatomic __copy_from_user - -extern unsigned long __must_check __copy_user(void __user *to, - const void *from, - unsigned long n); - -static inline unsigned long copy_to_user(void __user *to, const void *from, - unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - return __copy_user(to, from, n); - return n; -} - -#define __copy_to_user(to, from, n) __copy_user(to, from, n) -#define __copy_to_user_inatomic __copy_to_user +extern unsigned long raw_copy_from_user(void *to, const void __user *from, + unsigned long n); +extern unsigned long raw_copy_to_user(void __user *to, const void *from, + unsigned long n); /* * Zero Userspace diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c index 5fd16ee5280c..e615603a4b0a 100644 --- a/arch/metag/kernel/ptrace.c +++ b/arch/metag/kernel/ptrace.c @@ -26,6 +26,16 @@ * user_regset definitions. */ +static unsigned long user_txstatus(const struct pt_regs *regs) +{ + unsigned long data = (unsigned long)regs->ctx.Flags; + + if (regs->ctx.SaveMask & TBICTX_CBUF_BIT) + data |= USER_GP_REGS_STATUS_CATCH_BIT; + + return data; +} + int metag_gp_regs_copyout(const struct pt_regs *regs, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) @@ -64,9 +74,7 @@ int metag_gp_regs_copyout(const struct pt_regs *regs, if (ret) goto out; /* TXSTATUS */ - data = (unsigned long)regs->ctx.Flags; - if (regs->ctx.SaveMask & TBICTX_CBUF_BIT) - data |= USER_GP_REGS_STATUS_CATCH_BIT; + data = user_txstatus(regs); ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &data, 4*25, 4*26); if (ret) @@ -121,6 +129,7 @@ int metag_gp_regs_copyin(struct pt_regs *regs, if (ret) goto out; /* TXSTATUS */ + data = user_txstatus(regs); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &data, 4*25, 4*26); if (ret) @@ -246,6 +255,8 @@ int metag_rp_state_copyin(struct pt_regs *regs, unsigned long long *ptr; int ret, i; + if (count < 4*13) + return -EINVAL; /* Read the entire pipeline before making any changes */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &rp, 0, 4*13); @@ -305,7 +316,7 @@ static int metag_tls_set(struct task_struct *target, const void *kbuf, const void __user *ubuf) { int ret; - void __user *tls; + void __user *tls = target->thread.tls_ptr; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); if (ret) diff --git a/arch/metag/kernel/stacktrace.c b/arch/metag/kernel/stacktrace.c index 91ffc4b75c33..09d67b7f51ca 100644 --- a/arch/metag/kernel/stacktrace.c +++ b/arch/metag/kernel/stacktrace.c @@ -31,8 +31,6 @@ static void tbi_boing_init(void) } #endif -#define ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) - /* * Unwind the current stack frame and store the new register values in the * structure passed as argument. Unwinding is equivalent to a function return, diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c index b3ebfe9c8e88..e8a4ea83cabb 100644 --- a/arch/metag/lib/usercopy.c +++ b/arch/metag/lib/usercopy.c @@ -29,7 +29,6 @@ COPY \ "1:\n" \ " .section .fixup,\"ax\"\n" \ - " MOV D1Ar1,#0\n" \ FIXUP \ " MOVT D1Ar1,#HI(1b)\n" \ " JUMP D1Ar1,#LO(1b)\n" \ @@ -260,27 +259,31 @@ "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ "22:\n" \ "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "SUB %3, %3, #32\n" \ "23:\n" \ - "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "SUB %3, %3, #32\n" \ "24:\n" \ + "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "25:\n" \ "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "26:\n" \ "SUB %3, %3, #32\n" \ "DCACHE [%1+#-64], D0Ar6\n" \ "BR $Lloop"id"\n" \ \ "MOV RAPF, %1\n" \ - "25:\n" \ + "27:\n" \ "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "26:\n" \ + "28:\n" \ "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "29:\n" \ "SUB %3, %3, #32\n" \ - "27:\n" \ + "30:\n" \ "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "28:\n" \ + "31:\n" \ "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "32:\n" \ "SUB %0, %0, #8\n" \ - "29:\n" \ + "33:\n" \ "SETL [%0++], D0.7, D1.7\n" \ "SUB %3, %3, #32\n" \ "1:" \ @@ -312,11 +315,15 @@ " .long 26b,3b\n" \ " .long 27b,3b\n" \ " .long 28b,3b\n" \ - " .long 29b,4b\n" \ + " .long 29b,3b\n" \ + " .long 30b,3b\n" \ + " .long 31b,3b\n" \ + " .long 32b,3b\n" \ + " .long 33b,4b\n" \ " .previous\n" \ : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ : "0" (to), "1" (from), "2" (ret), "3" (n) \ - : "D1Ar1", "D0Ar2", "memory") + : "D1Ar1", "D0Ar2", "cc", "memory") /* rewind 'to' and 'from' pointers when a fault occurs * @@ -342,7 +349,7 @@ #define __asm_copy_to_user_64bit_rapf_loop(to, from, ret, n, id)\ __asm_copy_user_64bit_rapf_loop(to, from, ret, n, id, \ "LSR D0Ar2, D0Ar2, #8\n" \ - "AND D0Ar2, D0Ar2, #0x7\n" \ + "ANDS D0Ar2, D0Ar2, #0x7\n" \ "ADDZ D0Ar2, D0Ar2, #4\n" \ "SUB D0Ar2, D0Ar2, #1\n" \ "MOV D1Ar1, #4\n" \ @@ -403,47 +410,55 @@ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ "22:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "SUB %3, %3, #16\n" \ "23:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "24:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ "SUB %3, %3, #16\n" \ - "25:\n" \ + "24:\n" \ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "26:\n" \ + "25:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "26:\n" \ "SUB %3, %3, #16\n" \ "27:\n" \ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ "28:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "29:\n" \ + "SUB %3, %3, #16\n" \ + "30:\n" \ + "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "31:\n" \ + "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "32:\n" \ "SUB %3, %3, #16\n" \ "DCACHE [%1+#-64], D0Ar6\n" \ "BR $Lloop"id"\n" \ \ "MOV RAPF, %1\n" \ - "29:\n" \ + "33:\n" \ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "30:\n" \ + "34:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "35:\n" \ "SUB %3, %3, #16\n" \ - "31:\n" \ + "36:\n" \ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "32:\n" \ + "37:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "38:\n" \ "SUB %3, %3, #16\n" \ - "33:\n" \ + "39:\n" \ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "34:\n" \ + "40:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "41:\n" \ "SUB %3, %3, #16\n" \ - "35:\n" \ + "42:\n" \ "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "36:\n" \ + "43:\n" \ "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "44:\n" \ "SUB %0, %0, #4\n" \ - "37:\n" \ + "45:\n" \ "SETD [%0++], D0.7\n" \ "SUB %3, %3, #16\n" \ "1:" \ @@ -483,11 +498,19 @@ " .long 34b,3b\n" \ " .long 35b,3b\n" \ " .long 36b,3b\n" \ - " .long 37b,4b\n" \ + " .long 37b,3b\n" \ + " .long 38b,3b\n" \ + " .long 39b,3b\n" \ + " .long 40b,3b\n" \ + " .long 41b,3b\n" \ + " .long 42b,3b\n" \ + " .long 43b,3b\n" \ + " .long 44b,3b\n" \ + " .long 45b,4b\n" \ " .previous\n" \ : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ : "0" (to), "1" (from), "2" (ret), "3" (n) \ - : "D1Ar1", "D0Ar2", "memory") + : "D1Ar1", "D0Ar2", "cc", "memory") /* rewind 'to' and 'from' pointers when a fault occurs * @@ -513,7 +536,7 @@ #define __asm_copy_to_user_32bit_rapf_loop(to, from, ret, n, id)\ __asm_copy_user_32bit_rapf_loop(to, from, ret, n, id, \ "LSR D0Ar2, D0Ar2, #8\n" \ - "AND D0Ar2, D0Ar2, #0x7\n" \ + "ANDS D0Ar2, D0Ar2, #0x7\n" \ "ADDZ D0Ar2, D0Ar2, #4\n" \ "SUB D0Ar2, D0Ar2, #1\n" \ "MOV D1Ar1, #4\n" \ @@ -525,8 +548,8 @@ "SUB %1, %1, D0Ar2\n" \ "SUB %3, %3, D1Ar1\n") -unsigned long __copy_user(void __user *pdst, const void *psrc, - unsigned long n) +unsigned long raw_copy_to_user(void __user *pdst, const void *psrc, + unsigned long n) { register char __user *dst asm ("A0.2") = pdst; register const char *src asm ("A1.2") = psrc; @@ -538,23 +561,31 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, if ((unsigned long) src & 1) { __asm_copy_to_user_1(dst, src, retn); n--; + if (retn) + return retn + n; } if ((unsigned long) dst & 1) { /* Worst case - byte copy */ while (n > 0) { __asm_copy_to_user_1(dst, src, retn); n--; + if (retn) + return retn + n; } } if (((unsigned long) src & 2) && n >= 2) { __asm_copy_to_user_2(dst, src, retn); n -= 2; + if (retn) + return retn + n; } if ((unsigned long) dst & 2) { /* Second worst case - word copy */ while (n >= 2) { __asm_copy_to_user_2(dst, src, retn); n -= 2; + if (retn) + return retn + n; } } @@ -569,6 +600,8 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, while (n >= 8) { __asm_copy_to_user_8x64(dst, src, retn); n -= 8; + if (retn) + return retn + n; } } if (n >= RAPF_MIN_BUF_SIZE) { @@ -581,6 +614,8 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, while (n >= 8) { __asm_copy_to_user_8x64(dst, src, retn); n -= 8; + if (retn) + return retn + n; } } #endif @@ -588,11 +623,15 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, while (n >= 16) { __asm_copy_to_user_16(dst, src, retn); n -= 16; + if (retn) + return retn + n; } while (n >= 4) { __asm_copy_to_user_4(dst, src, retn); n -= 4; + if (retn) + return retn + n; } switch (n) { @@ -609,24 +648,26 @@ unsigned long __copy_user(void __user *pdst, const void *psrc, break; } + /* + * If we get here, retn correctly reflects the number of failing + * bytes. + */ return retn; } -EXPORT_SYMBOL(__copy_user); +EXPORT_SYMBOL(raw_copy_to_user); #define __asm_copy_from_user_1(to, from, ret) \ __asm_copy_user_cont(to, from, ret, \ " GETB D1Ar1,[%1++]\n" \ "2: SETB [%0++],D1Ar1\n", \ - "3: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ + "3: ADD %2,%2,#1\n", \ " .long 2b,3b\n") #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ __asm_copy_user_cont(to, from, ret, \ " GETW D1Ar1,[%1++]\n" \ "2: SETW [%0++],D1Ar1\n" COPY, \ - "3: ADD %2,%2,#2\n" \ - " SETW [%0++],D1Ar1\n" FIXUP, \ + "3: ADD %2,%2,#2\n" FIXUP, \ " .long 2b,3b\n" TENTRY) #define __asm_copy_from_user_2(to, from, ret) \ @@ -636,145 +677,26 @@ EXPORT_SYMBOL(__copy_user); __asm_copy_from_user_2x_cont(to, from, ret, \ " GETB D1Ar1,[%1++]\n" \ "4: SETB [%0++],D1Ar1\n", \ - "5: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ + "5: ADD %2,%2,#1\n", \ " .long 4b,5b\n") #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ __asm_copy_user_cont(to, from, ret, \ " GETD D1Ar1,[%1++]\n" \ "2: SETD [%0++],D1Ar1\n" COPY, \ - "3: ADD %2,%2,#4\n" \ - " SETD [%0++],D1Ar1\n" FIXUP, \ + "3: ADD %2,%2,#4\n" FIXUP, \ " .long 2b,3b\n" TENTRY) #define __asm_copy_from_user_4(to, from, ret) \ __asm_copy_from_user_4x_cont(to, from, ret, "", "", "") -#define __asm_copy_from_user_5(to, from, ret) \ - __asm_copy_from_user_4x_cont(to, from, ret, \ - " GETB D1Ar1,[%1++]\n" \ - "4: SETB [%0++],D1Ar1\n", \ - "5: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ - " .long 4b,5b\n") - -#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ - __asm_copy_from_user_4x_cont(to, from, ret, \ - " GETW D1Ar1,[%1++]\n" \ - "4: SETW [%0++],D1Ar1\n" COPY, \ - "5: ADD %2,%2,#2\n" \ - " SETW [%0++],D1Ar1\n" FIXUP, \ - " .long 4b,5b\n" TENTRY) - -#define __asm_copy_from_user_6(to, from, ret) \ - __asm_copy_from_user_6x_cont(to, from, ret, "", "", "") - -#define __asm_copy_from_user_7(to, from, ret) \ - __asm_copy_from_user_6x_cont(to, from, ret, \ - " GETB D1Ar1,[%1++]\n" \ - "6: SETB [%0++],D1Ar1\n", \ - "7: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ - " .long 6b,7b\n") - -#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ - __asm_copy_from_user_4x_cont(to, from, ret, \ - " GETD D1Ar1,[%1++]\n" \ - "4: SETD [%0++],D1Ar1\n" COPY, \ - "5: ADD %2,%2,#4\n" \ - " SETD [%0++],D1Ar1\n" FIXUP, \ - " .long 4b,5b\n" TENTRY) - -#define __asm_copy_from_user_8(to, from, ret) \ - __asm_copy_from_user_8x_cont(to, from, ret, "", "", "") - -#define __asm_copy_from_user_9(to, from, ret) \ - __asm_copy_from_user_8x_cont(to, from, ret, \ - " GETB D1Ar1,[%1++]\n" \ - "6: SETB [%0++],D1Ar1\n", \ - "7: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ - " .long 6b,7b\n") - -#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ - __asm_copy_from_user_8x_cont(to, from, ret, \ - " GETW D1Ar1,[%1++]\n" \ - "6: SETW [%0++],D1Ar1\n" COPY, \ - "7: ADD %2,%2,#2\n" \ - " SETW [%0++],D1Ar1\n" FIXUP, \ - " .long 6b,7b\n" TENTRY) - -#define __asm_copy_from_user_10(to, from, ret) \ - __asm_copy_from_user_10x_cont(to, from, ret, "", "", "") - -#define __asm_copy_from_user_11(to, from, ret) \ - __asm_copy_from_user_10x_cont(to, from, ret, \ - " GETB D1Ar1,[%1++]\n" \ - "8: SETB [%0++],D1Ar1\n", \ - "9: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ - " .long 8b,9b\n") - -#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ - __asm_copy_from_user_8x_cont(to, from, ret, \ - " GETD D1Ar1,[%1++]\n" \ - "6: SETD [%0++],D1Ar1\n" COPY, \ - "7: ADD %2,%2,#4\n" \ - " SETD [%0++],D1Ar1\n" FIXUP, \ - " .long 6b,7b\n" TENTRY) - -#define __asm_copy_from_user_12(to, from, ret) \ - __asm_copy_from_user_12x_cont(to, from, ret, "", "", "") - -#define __asm_copy_from_user_13(to, from, ret) \ - __asm_copy_from_user_12x_cont(to, from, ret, \ - " GETB D1Ar1,[%1++]\n" \ - "8: SETB [%0++],D1Ar1\n", \ - "9: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ - " .long 8b,9b\n") - -#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ - __asm_copy_from_user_12x_cont(to, from, ret, \ - " GETW D1Ar1,[%1++]\n" \ - "8: SETW [%0++],D1Ar1\n" COPY, \ - "9: ADD %2,%2,#2\n" \ - " SETW [%0++],D1Ar1\n" FIXUP, \ - " .long 8b,9b\n" TENTRY) - -#define __asm_copy_from_user_14(to, from, ret) \ - __asm_copy_from_user_14x_cont(to, from, ret, "", "", "") - -#define __asm_copy_from_user_15(to, from, ret) \ - __asm_copy_from_user_14x_cont(to, from, ret, \ - " GETB D1Ar1,[%1++]\n" \ - "10: SETB [%0++],D1Ar1\n", \ - "11: ADD %2,%2,#1\n" \ - " SETB [%0++],D1Ar1\n", \ - " .long 10b,11b\n") - -#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ - __asm_copy_from_user_12x_cont(to, from, ret, \ - " GETD D1Ar1,[%1++]\n" \ - "8: SETD [%0++],D1Ar1\n" COPY, \ - "9: ADD %2,%2,#4\n" \ - " SETD [%0++],D1Ar1\n" FIXUP, \ - " .long 8b,9b\n" TENTRY) - -#define __asm_copy_from_user_16(to, from, ret) \ - __asm_copy_from_user_16x_cont(to, from, ret, "", "", "") - #define __asm_copy_from_user_8x64(to, from, ret) \ asm volatile ( \ " GETL D0Ar2,D1Ar1,[%1++]\n" \ "2: SETL [%0++],D0Ar2,D1Ar1\n" \ "1:\n" \ " .section .fixup,\"ax\"\n" \ - " MOV D1Ar1,#0\n" \ - " MOV D0Ar2,#0\n" \ "3: ADD %2,%2,#8\n" \ - " SETL [%0++],D0Ar2,D1Ar1\n" \ " MOVT D0Ar2,#HI(1b)\n" \ " JUMP D0Ar2,#LO(1b)\n" \ " .previous\n" \ @@ -789,36 +711,57 @@ EXPORT_SYMBOL(__copy_user); * * Rationale: * A fault occurs while reading from user buffer, which is the - * source. Since the fault is at a single address, we only - * need to rewind by 8 bytes. + * source. * Since we don't write to kernel buffer until we read first, * the kernel buffer is at the right state and needn't be - * corrected. + * corrected, but the source must be rewound to the beginning of + * the block, which is LSM_STEP*8 bytes. + * LSM_STEP is bits 10:8 in TXSTATUS which is already read + * and stored in D0Ar2 + * + * NOTE: If a fault occurs at the last operation in M{G,S}ETL + * LSM_STEP will be 0. ie: we do 4 writes in our case, if + * a fault happens at the 4th write, LSM_STEP will be 0 + * instead of 4. The code copes with that. */ #define __asm_copy_from_user_64bit_rapf_loop(to, from, ret, n, id) \ __asm_copy_user_64bit_rapf_loop(to, from, ret, n, id, \ - "SUB %1, %1, #8\n") + "LSR D0Ar2, D0Ar2, #5\n" \ + "ANDS D0Ar2, D0Ar2, #0x38\n" \ + "ADDZ D0Ar2, D0Ar2, #32\n" \ + "SUB %1, %1, D0Ar2\n") /* rewind 'from' pointer when a fault occurs * * Rationale: * A fault occurs while reading from user buffer, which is the - * source. Since the fault is at a single address, we only - * need to rewind by 4 bytes. + * source. * Since we don't write to kernel buffer until we read first, * the kernel buffer is at the right state and needn't be - * corrected. + * corrected, but the source must be rewound to the beginning of + * the block, which is LSM_STEP*4 bytes. + * LSM_STEP is bits 10:8 in TXSTATUS which is already read + * and stored in D0Ar2 + * + * NOTE: If a fault occurs at the last operation in M{G,S}ETL + * LSM_STEP will be 0. ie: we do 4 writes in our case, if + * a fault happens at the 4th write, LSM_STEP will be 0 + * instead of 4. The code copes with that. */ #define __asm_copy_from_user_32bit_rapf_loop(to, from, ret, n, id) \ __asm_copy_user_32bit_rapf_loop(to, from, ret, n, id, \ - "SUB %1, %1, #4\n") + "LSR D0Ar2, D0Ar2, #6\n" \ + "ANDS D0Ar2, D0Ar2, #0x1c\n" \ + "ADDZ D0Ar2, D0Ar2, #16\n" \ + "SUB %1, %1, D0Ar2\n") -/* Copy from user to kernel, zeroing the bytes that were inaccessible in - userland. The return-value is the number of bytes that were - inaccessible. */ -unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, - unsigned long n) +/* + * Copy from user to kernel. The return-value is the number of bytes that were + * inaccessible. + */ +unsigned long raw_copy_from_user(void *pdst, const void __user *psrc, + unsigned long n) { register char *dst asm ("A0.2") = pdst; register const char __user *src asm ("A1.2") = psrc; @@ -830,6 +773,8 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, if ((unsigned long) src & 1) { __asm_copy_from_user_1(dst, src, retn); n--; + if (retn) + return retn + n; } if ((unsigned long) dst & 1) { /* Worst case - byte copy */ @@ -837,12 +782,14 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, __asm_copy_from_user_1(dst, src, retn); n--; if (retn) - goto copy_exception_bytes; + return retn + n; } } if (((unsigned long) src & 2) && n >= 2) { __asm_copy_from_user_2(dst, src, retn); n -= 2; + if (retn) + return retn + n; } if ((unsigned long) dst & 2) { /* Second worst case - word copy */ @@ -850,16 +797,10 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, __asm_copy_from_user_2(dst, src, retn); n -= 2; if (retn) - goto copy_exception_bytes; + return retn + n; } } - /* We only need one check after the unalignment-adjustments, - because if both adjustments were done, either both or - neither reference had an exception. */ - if (retn != 0) - goto copy_exception_bytes; - #ifdef USE_RAPF /* 64 bit copy loop */ if (!(((unsigned long) src | (unsigned long) dst) & 7)) { @@ -872,7 +813,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, __asm_copy_from_user_8x64(dst, src, retn); n -= 8; if (retn) - goto copy_exception_bytes; + return retn + n; } } @@ -888,7 +829,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, __asm_copy_from_user_8x64(dst, src, retn); n -= 8; if (retn) - goto copy_exception_bytes; + return retn + n; } } #endif @@ -898,7 +839,7 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, n -= 4; if (retn) - goto copy_exception_bytes; + return retn + n; } /* If we get here, there were no memory read faults. */ @@ -924,21 +865,8 @@ unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, /* If we get here, retn correctly reflects the number of failing bytes. */ return retn; - - copy_exception_bytes: - /* We already have "retn" bytes cleared, and need to clear the - remaining "n" bytes. A non-optimized simple byte-for-byte in-line - memset is preferred here, since this isn't speed-critical code and - we'd rather have this a leaf-function than calling memset. */ - { - char *endp; - for (endp = dst + n; dst < endp; dst++) - *dst = 0; - } - - return retn + n; } -EXPORT_SYMBOL(__copy_user_zeroing); +EXPORT_SYMBOL(raw_copy_from_user); #define __asm_clear_8x64(to, ret) \ asm volatile ( \ diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index 1732ec13b211..56830ff65333 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@ -3,6 +3,7 @@ generic-y += barrier.h generic-y += clkdev.h generic-y += device.h generic-y += exec.h +generic-y += extable.h generic-y += irq_work.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index fd850879854d..d506bb0893f9 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -95,7 +95,8 @@ typedef struct { unsigned long pgd; } pgd_t; # else /* CONFIG_MMU */ typedef struct { unsigned long ste[64]; } pmd_t; typedef struct { pmd_t pue[1]; } pud_t; -typedef struct { pud_t pge[1]; } pgd_t; +typedef struct { pud_t p4e[1]; } p4d_t; +typedef struct { p4d_t pge[1]; } pgd_t; # endif /* CONFIG_MMU */ # define pte_val(x) ((x).pte) diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 253a67e275ad..38f2c9ccef10 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -11,22 +11,15 @@ #ifndef _ASM_MICROBLAZE_UACCESS_H #define _ASM_MICROBLAZE_UACCESS_H -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ - #include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/sched.h> /* RLIMIT_FSIZE */ #include <linux/mm.h> #include <asm/mmu.h> #include <asm/page.h> #include <asm/pgtable.h> +#include <asm/extable.h> #include <linux/string.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - /* * On Microblaze the fs value is actually the top of the corresponding * address space. @@ -55,22 +48,6 @@ # define segment_eq(a, b) ((a).seg == (b).seg) -/* - * 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; -}; - #ifndef CONFIG_MMU /* Check against bounds of physical memory */ @@ -359,39 +336,19 @@ extern long __user_bad(void); __gu_err; \ }) - -/* copy_to_from_user */ -#define __copy_from_user(to, from, n) \ - __copy_tofrom_user((__force void __user *)(to), \ - (void __user *)(from), (n)) -#define __copy_from_user_inatomic(to, from, n) \ - __copy_from_user((to), (from), (n)) - -static inline long copy_from_user(void *to, - const void __user *from, unsigned long n) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - unsigned long res = n; - might_fault(); - if (likely(access_ok(VERIFY_READ, from, n))) - res = __copy_from_user(to, from, n); - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; + return __copy_tofrom_user((__force void __user *)to, from, n); } -#define __copy_to_user(to, from, n) \ - __copy_tofrom_user((void __user *)(to), \ - (__force const void __user *)(from), (n)) -#define __copy_to_user_inatomic(to, from, n) __copy_to_user((to), (from), (n)) - -static inline long copy_to_user(void __user *to, - const void *from, unsigned long n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - might_fault(); - if (access_ok(VERIFY_WRITE, to, n)) - return __copy_to_user(to, from, n); - return n; + return __copy_tofrom_user(to, (__force const void __user *)from, n); } +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * Copy a null terminated string from userspace. @@ -422,7 +379,4 @@ static inline long strnlen_user(const char __user *src, long n) return __strnlen_user(src, n); } -#endif /* __ASSEMBLY__ */ -#endif /* __KERNEL__ */ - #endif /* _ASM_MICROBLAZE_UACCESS_H */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index a008a9f03072..d6d545a45118 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -68,7 +68,6 @@ config MIPS select HANDLE_DOMAIN_IRQ select HAVE_EXIT_THREAD select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_ARCH_HARDENED_USERCOPY menu "Machine selection" @@ -1531,7 +1530,7 @@ config CPU_MIPS64_R6 select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_MSA select GENERIC_CSUM - select MIPS_O32_FP64_SUPPORT if MIPS32_O32 + select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32 select HAVE_KVM help Choose this option to build a kernel for release 6 or later of the diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 8ef9c02747fa..02a1787c888c 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -489,7 +489,7 @@ $(generic_defconfigs): $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \ -m -O $(objtree) $(srctree)/arch/$(ARCH)/configs/generic_defconfig $^ \ $(foreach board,$(BOARDS),$(generic_config_dir)/board-$(board).config) - $(Q)$(MAKE) olddefconfig + $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig # # Prevent generic merge_config rules attempting to merge single fragments @@ -503,8 +503,8 @@ $(generic_config_dir)/%.config: ; # .PHONY: sead3_defconfig sead3_defconfig: - $(Q)$(MAKE) 32r2el_defconfig BOARDS=sead-3 + $(Q)$(MAKE) -f $(srctree)/Makefile 32r2el_defconfig BOARDS=sead-3 .PHONY: sead3micro_defconfig sead3micro_defconfig: - $(Q)$(MAKE) micro32r2el_defconfig BOARDS=sead-3 + $(Q)$(MAKE) -f $(srctree)/Makefile micro32r2el_defconfig BOARDS=sead-3 diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c index e1bec5a77c39..32d1333bb243 100644 --- a/arch/mips/alchemy/common/time.c +++ b/arch/mips/alchemy/common/time.c @@ -138,7 +138,9 @@ static int __init alchemy_time_init(unsigned int m2int) cd->shift = 32; cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift); cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(9, cd); /* ~0.28ms */ + cd->max_delta_ticks = 0xffffffff; + cd->min_delta_ns = clockevent_delta2ns(9, cd); + cd->min_delta_ticks = 9; /* ~0.28ms */ clockevents_register_device(cd); setup_irq(m2int, &au1x_rtcmatch2_irqaction); diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c index a5b427909b5c..036d56cc4591 100644 --- a/arch/mips/cavium-octeon/cpu.c +++ b/arch/mips/cavium-octeon/cpu.c @@ -10,7 +10,9 @@ #include <linux/irqflags.h> #include <linux/notifier.h> #include <linux/prefetch.h> +#include <linux/ptrace.h> #include <linux/sched.h> +#include <linux/sched/task_stack.h> #include <asm/cop2.h> #include <asm/current.h> diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.c b/arch/mips/cavium-octeon/crypto/octeon-crypto.c index 4d22365844af..cfb4a146cf17 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.c +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.c @@ -9,6 +9,7 @@ #include <asm/cop2.h> #include <linux/export.h> #include <linux/interrupt.h> +#include <linux/sched/task_stack.h> #include "octeon-crypto.h" diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S index cfd97f6448bb..0a7c9834b81c 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S @@ -140,15 +140,6 @@ .set noat /* - * t7 is used as a flag to note inatomic mode. - */ -LEAF(__copy_user_inatomic) -EXPORT_SYMBOL(__copy_user_inatomic) - b __copy_user_common - li t7, 1 - END(__copy_user_inatomic) - -/* * A combined memcpy/__copy_user * __copy_user sets len to 0 for success; else to an upper bound of * the number of uncopied bytes. @@ -161,8 +152,6 @@ EXPORT_SYMBOL(memcpy) __memcpy: FEXPORT(__copy_user) EXPORT_SYMBOL(__copy_user) - li t7, 0 /* not inatomic */ -__copy_user_common: /* * Note: dst & src may be unaligned, len may be 0 * Temps @@ -414,25 +403,7 @@ l_exc: LOAD t0, TI_TASK($28) LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address SUB len, AT, t0 # len number of uncopied bytes - bnez t7, 2f /* Skip the zeroing out part if inatomic */ - /* - * Here's where we rely on src and dst being incremented in tandem, - * See (3) above. - * dst += (fault addr - src) to put dst at first byte to clear - */ - ADD dst, t0 # compute start address in a1 - SUB dst, src - /* - * Clear len bytes starting at dst. Can't call __bzero because it - * might modify len. An inefficient loop for these rare times... - */ - beqz len, done - SUB src, len, 1 -1: sb zero, 0(dst) - ADD dst, dst, 1 - bnez src, 1b - SUB src, src, 1 -2: jr ra + jr ra nop diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 4b94b7fbafa3..3de786545ded 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -12,6 +12,7 @@ #include <linux/kernel_stat.h> #include <linux/sched.h> #include <linux/sched/hotplug.h> +#include <linux/sched/task_stack.h> #include <linux/init.h> #include <linux/export.h> diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig index 31e3c4d9adb0..d4fda41f00ba 100644 --- a/arch/mips/configs/cavium_octeon_defconfig +++ b/arch/mips/configs/cavium_octeon_defconfig @@ -127,6 +127,11 @@ CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD_PLATFORM=m CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_HCD_PLATFORM=m +CONFIG_MMC=y +# CONFIG_PWRSEQ_EMMC is not set +# CONFIG_PWRSEQ_SIMPLE is not set +# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_MMC_CAVIUM_OCTEON=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_STAGING=y diff --git a/arch/mips/include/asm/asm-prototypes.h b/arch/mips/include/asm/asm-prototypes.h index a160cf69bb92..6e28971fe73a 100644 --- a/arch/mips/include/asm/asm-prototypes.h +++ b/arch/mips/include/asm/asm-prototypes.h @@ -3,3 +3,4 @@ #include <asm/fpu.h> #include <asm-generic/asm-prototypes.h> #include <asm/uaccess.h> +#include <asm/ftrace.h> diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index c8b574f7e0cc..77cad232a1c6 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -50,7 +50,7 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) { might_fault(); - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) return __csum_partial_copy_kernel((__force void *)src, dst, len, sum, err_ptr); else @@ -82,7 +82,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, { might_fault(); if (access_ok(VERIFY_WRITE, dst, len)) { - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) return __csum_partial_copy_kernel(src, (__force void *)dst, len, sum, err_ptr); diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h index 321752bcbab6..a2813fe381cf 100644 --- a/arch/mips/include/asm/fpu.h +++ b/arch/mips/include/asm/fpu.h @@ -12,6 +12,7 @@ #include <linux/sched.h> #include <linux/sched/task_stack.h> +#include <linux/ptrace.h> #include <linux/thread_info.h> #include <linux/bitops.h> @@ -20,6 +21,7 @@ #include <asm/cpu-features.h> #include <asm/fpu_emulator.h> #include <asm/hazards.h> +#include <asm/ptrace.h> #include <asm/processor.h> #include <asm/current.h> #include <asm/msa.h> diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 956db6e201d1..ddd1c918103b 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -18,9 +18,24 @@ #include <irq.h> #define IRQ_STACK_SIZE THREAD_SIZE +#define IRQ_STACK_START (IRQ_STACK_SIZE - sizeof(unsigned long)) extern void *irq_stack[NR_CPUS]; +/* + * The highest address on the IRQ stack contains a dummy frame put down in + * genex.S (handle_int & except_vec_vi_handler) which is structured as follows: + * + * top ------------ + * | task sp | <- irq_stack[cpu] + IRQ_STACK_START + * ------------ + * | | <- First frame of IRQ context + * ------------ + * + * task sp holds a copy of the task stack pointer where the struct pt_regs + * from exception entry can be found. + */ + static inline bool on_irq_stack(int cpu, unsigned long sp) { unsigned long low = (unsigned long)irq_stack[cpu]; diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index d21f3da7bdb6..6f94bed571c4 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -16,6 +16,7 @@ #include <asm/cachectl.h> #include <asm/fixmap.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> extern int temp_tlb_entry; diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index 514cbc0a6a67..130a2a6c1531 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -17,6 +17,7 @@ #include <asm/cachectl.h> #include <asm/fixmap.h> +#define __ARCH_USE_5LEVEL_HACK #if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48) #include <asm-generic/pgtable-nopmd.h> #else diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index 55fd94e6cd0b..7f12d7e27c94 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h @@ -20,7 +20,7 @@ #include <asm/cpu-features.h> #include <asm/cpu-type.h> #include <asm/mipsmtregs.h> -#include <linux/uaccess.h> /* for segment_eq() */ +#include <linux/uaccess.h> /* for uaccess_kernel() */ extern void (*r4k_blast_dcache)(void); extern void (*r4k_blast_icache)(void); @@ -714,7 +714,7 @@ static inline void protected_blast_##pfx##cache##_range(unsigned long start,\ \ __##pfx##flush_prologue \ \ - if (segment_eq(get_fs(), USER_DS)) { \ + if (!uaccess_kernel()) { \ while (1) { \ protected_cachee_op(hitop, addr); \ if (addr == aend) \ diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index f485afe51514..a8df44d60607 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h @@ -127,7 +127,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) " andi %[ticket], %[ticket], 0xffff \n" " bne %[ticket], %[my_ticket], 4f \n" " subu %[ticket], %[my_ticket], %[ticket] \n" - "2: \n" + "2: .insn \n" " .subsection 2 \n" "4: andi %[ticket], %[ticket], 0xffff \n" " sll %[ticket], 5 \n" @@ -202,7 +202,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) " sc %[ticket], %[ticket_ptr] \n" " beqz %[ticket], 1b \n" " li %[ticket], 1 \n" - "2: \n" + "2: .insn \n" " .subsection 2 \n" "3: b 2b \n" " li %[ticket], 0 \n" @@ -382,7 +382,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) " .set reorder \n" __WEAK_LLSC_MB " li %2, 1 \n" - "2: \n" + "2: .insn \n" : "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret) : GCC_OFF_SMALL_ASM() (rw->lock) : "memory"); @@ -422,7 +422,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) " lui %1, 0x8000 \n" " sc %1, %0 \n" " li %2, 1 \n" - "2: \n" + "2: .insn \n" : "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret) : GCC_OFF_SMALL_ASM() (rw->lock) diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index 5347cfe15af2..99e629a590a5 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -12,8 +12,6 @@ #define _ASM_UACCESS_H #include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/thread_info.h> #include <linux/string.h> #include <asm/asm-eva.h> #include <asm/extable.h> @@ -71,9 +69,6 @@ extern u64 __ua_limit; #define USER_DS ((mm_segment_t) { __UA_LIMIT }) #endif -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) #define set_fs(x) (current_thread_info()->addr_limit = (x)) @@ -93,7 +88,7 @@ static inline bool eva_kernel_access(void) if (!IS_ENABLED(CONFIG_EVA)) return false; - return segment_eq(get_fs(), get_ds()); + return uaccess_kernel(); } /* @@ -133,23 +128,14 @@ static inline bool eva_kernel_access(void) * this function, memory access functions may still return -EFAULT. */ -#define __access_mask get_fs().seg - -#define __access_ok(addr, size, mask) \ -({ \ - unsigned long __addr = (unsigned long) (addr); \ - unsigned long __size = size; \ - unsigned long __mask = mask; \ - unsigned long __ok; \ - \ - __chk_user_ptr(addr); \ - __ok = (signed long)(__mask & (__addr | (__addr + __size) | \ - __ua_size(__size))); \ - __ok == 0; \ -}) +static inline int __access_ok(const void __user *p, unsigned long size) +{ + unsigned long addr = (unsigned long)p; + return (get_fs().seg & (addr | (addr + size) | __ua_size(size))) == 0; +} #define access_ok(type, addr, size) \ - likely(__access_ok((addr), (size), __access_mask)) + likely(__access_ok((addr), (size))) /* * put_user: - Write a simple value into user space. @@ -811,157 +797,7 @@ extern void __put_user_unaligned_unknown(void); extern size_t __copy_user(void *__to, const void *__from, size_t __n); -#ifndef CONFIG_EVA -#define __invoke_copy_to_user(to, from, n) \ -({ \ - register void __user *__cu_to_r __asm__("$4"); \ - register const void *__cu_from_r __asm__("$5"); \ - register long __cu_len_r __asm__("$6"); \ - \ - __cu_to_r = (to); \ - __cu_from_r = (from); \ - __cu_len_r = (n); \ - __asm__ __volatile__( \ - __MODULE_JAL(__copy_user) \ - : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ - : \ - : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ - DADDI_SCRATCH, "memory"); \ - __cu_len_r; \ -}) - -#define __invoke_copy_to_kernel(to, from, n) \ - __invoke_copy_to_user(to, from, n) - -#endif - -/* - * __copy_to_user: - Copy a block of data into user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -#define __copy_to_user(to, from, n) \ -({ \ - void __user *__cu_to; \ - const void *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - \ - check_object_size(__cu_from, __cu_len, true); \ - might_fault(); \ - \ - if (eva_kernel_access()) \ - __cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \ - __cu_len); \ - else \ - __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, \ - __cu_len); \ - __cu_len; \ -}) - -extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); - -#define __copy_to_user_inatomic(to, from, n) \ -({ \ - void __user *__cu_to; \ - const void *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - \ - check_object_size(__cu_from, __cu_len, true); \ - \ - if (eva_kernel_access()) \ - __cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \ - __cu_len); \ - else \ - __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, \ - __cu_len); \ - __cu_len; \ -}) - -#define __copy_from_user_inatomic(to, from, n) \ -({ \ - void *__cu_to; \ - const void __user *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - \ - check_object_size(__cu_to, __cu_len, false); \ - \ - if (eva_kernel_access()) \ - __cu_len = __invoke_copy_from_kernel_inatomic(__cu_to, \ - __cu_from,\ - __cu_len);\ - else \ - __cu_len = __invoke_copy_from_user_inatomic(__cu_to, \ - __cu_from, \ - __cu_len); \ - __cu_len; \ -}) - -/* - * copy_to_user: - Copy a block of data into user space. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -#define copy_to_user(to, from, n) \ -({ \ - void __user *__cu_to; \ - const void *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - \ - check_object_size(__cu_from, __cu_len, true); \ - \ - if (eva_kernel_access()) { \ - __cu_len = __invoke_copy_to_kernel(__cu_to, \ - __cu_from, \ - __cu_len); \ - } else { \ - if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) { \ - might_fault(); \ - __cu_len = __invoke_copy_to_user(__cu_to, \ - __cu_from, \ - __cu_len); \ - } \ - } \ - __cu_len; \ -}) - -#ifndef CONFIG_EVA - -#define __invoke_copy_from_user(to, from, n) \ +#define __invoke_copy_from(func, to, from, n) \ ({ \ register void *__cu_to_r __asm__("$4"); \ register const void __user *__cu_from_r __asm__("$5"); \ @@ -972,7 +808,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); __cu_len_r = (n); \ __asm__ __volatile__( \ ".set\tnoreorder\n\t" \ - __MODULE_JAL(__copy_user) \ + __MODULE_JAL(func) \ ".set\tnoat\n\t" \ __UA_ADDU "\t$1, %1, %2\n\t" \ ".set\tat\n\t" \ @@ -984,33 +820,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); __cu_len_r; \ }) -#define __invoke_copy_from_kernel(to, from, n) \ - __invoke_copy_from_user(to, from, n) - -/* For userland <-> userland operations */ -#define ___invoke_copy_in_user(to, from, n) \ - __invoke_copy_from_user(to, from, n) - -/* For kernel <-> kernel operations */ -#define ___invoke_copy_in_kernel(to, from, n) \ - __invoke_copy_from_user(to, from, n) - -#define __invoke_copy_from_user_inatomic(to, from, n) \ +#define __invoke_copy_to(func, to, from, n) \ ({ \ - register void *__cu_to_r __asm__("$4"); \ - register const void __user *__cu_from_r __asm__("$5"); \ + register void __user *__cu_to_r __asm__("$4"); \ + register const void *__cu_from_r __asm__("$5"); \ register long __cu_len_r __asm__("$6"); \ \ __cu_to_r = (to); \ __cu_from_r = (from); \ __cu_len_r = (n); \ __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - __MODULE_JAL(__copy_user_inatomic) \ - ".set\tnoat\n\t" \ - __UA_ADDU "\t$1, %1, %2\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" \ + __MODULE_JAL(func) \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : \ : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ @@ -1018,228 +838,79 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); __cu_len_r; \ }) -#define __invoke_copy_from_kernel_inatomic(to, from, n) \ - __invoke_copy_from_user_inatomic(to, from, n) \ +#define __invoke_copy_from_kernel(to, from, n) \ + __invoke_copy_from(__copy_user, to, from, n) + +#define __invoke_copy_to_kernel(to, from, n) \ + __invoke_copy_to(__copy_user, to, from, n) + +#define ___invoke_copy_in_kernel(to, from, n) \ + __invoke_copy_from(__copy_user, to, from, n) + +#ifndef CONFIG_EVA +#define __invoke_copy_from_user(to, from, n) \ + __invoke_copy_from(__copy_user, to, from, n) + +#define __invoke_copy_to_user(to, from, n) \ + __invoke_copy_to(__copy_user, to, from, n) + +#define ___invoke_copy_in_user(to, from, n) \ + __invoke_copy_from(__copy_user, to, from, n) #else /* EVA specific functions */ -extern size_t __copy_user_inatomic_eva(void *__to, const void *__from, - size_t __n); extern size_t __copy_from_user_eva(void *__to, const void *__from, size_t __n); extern size_t __copy_to_user_eva(void *__to, const void *__from, size_t __n); extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n); -#define __invoke_copy_from_user_eva_generic(to, from, n, func_ptr) \ -({ \ - register void *__cu_to_r __asm__("$4"); \ - register const void __user *__cu_from_r __asm__("$5"); \ - register long __cu_len_r __asm__("$6"); \ - \ - __cu_to_r = (to); \ - __cu_from_r = (from); \ - __cu_len_r = (n); \ - __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - __MODULE_JAL(func_ptr) \ - ".set\tnoat\n\t" \ - __UA_ADDU "\t$1, %1, %2\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" \ - : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ - : \ - : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ - DADDI_SCRATCH, "memory"); \ - __cu_len_r; \ -}) - -#define __invoke_copy_to_user_eva_generic(to, from, n, func_ptr) \ -({ \ - register void *__cu_to_r __asm__("$4"); \ - register const void __user *__cu_from_r __asm__("$5"); \ - register long __cu_len_r __asm__("$6"); \ - \ - __cu_to_r = (to); \ - __cu_from_r = (from); \ - __cu_len_r = (n); \ - __asm__ __volatile__( \ - __MODULE_JAL(func_ptr) \ - : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ - : \ - : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ - DADDI_SCRATCH, "memory"); \ - __cu_len_r; \ -}) - /* * Source or destination address is in userland. We need to go through * the TLB */ #define __invoke_copy_from_user(to, from, n) \ - __invoke_copy_from_user_eva_generic(to, from, n, __copy_from_user_eva) - -#define __invoke_copy_from_user_inatomic(to, from, n) \ - __invoke_copy_from_user_eva_generic(to, from, n, \ - __copy_user_inatomic_eva) + __invoke_copy_from(__copy_from_user_eva, to, from, n) #define __invoke_copy_to_user(to, from, n) \ - __invoke_copy_to_user_eva_generic(to, from, n, __copy_to_user_eva) + __invoke_copy_to(__copy_to_user_eva, to, from, n) #define ___invoke_copy_in_user(to, from, n) \ - __invoke_copy_from_user_eva_generic(to, from, n, __copy_in_user_eva) - -/* - * Source or destination address in the kernel. We are not going through - * the TLB - */ -#define __invoke_copy_from_kernel(to, from, n) \ - __invoke_copy_from_user_eva_generic(to, from, n, __copy_user) - -#define __invoke_copy_from_kernel_inatomic(to, from, n) \ - __invoke_copy_from_user_eva_generic(to, from, n, __copy_user_inatomic) - -#define __invoke_copy_to_kernel(to, from, n) \ - __invoke_copy_to_user_eva_generic(to, from, n, __copy_user) - -#define ___invoke_copy_in_kernel(to, from, n) \ - __invoke_copy_from_user_eva_generic(to, from, n, __copy_user) + __invoke_copy_from(__copy_in_user_eva, to, from, n) #endif /* CONFIG_EVA */ -/* - * __copy_from_user: - Copy a block of data from user space, with less checking. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -#define __copy_from_user(to, from, n) \ -({ \ - void *__cu_to; \ - const void __user *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - \ - check_object_size(__cu_to, __cu_len, false); \ - \ - if (eva_kernel_access()) { \ - __cu_len = __invoke_copy_from_kernel(__cu_to, \ - __cu_from, \ - __cu_len); \ - } else { \ - might_fault(); \ - __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \ - __cu_len); \ - } \ - __cu_len; \ -}) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) +{ + if (eva_kernel_access()) + return __invoke_copy_to_kernel(to, from, n); + else + return __invoke_copy_to_user(to, from, n); +} -/* - * copy_from_user: - Copy a block of data from user space. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -#define copy_from_user(to, from, n) \ -({ \ - void *__cu_to; \ - const void __user *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - \ - check_object_size(__cu_to, __cu_len, false); \ - \ - if (eva_kernel_access()) { \ - __cu_len = __invoke_copy_from_kernel(__cu_to, \ - __cu_from, \ - __cu_len); \ - } else { \ - if (access_ok(VERIFY_READ, __cu_from, __cu_len)) { \ - might_fault(); \ - __cu_len = __invoke_copy_from_user(__cu_to, \ - __cu_from, \ - __cu_len); \ - } else { \ - memset(__cu_to, 0, __cu_len); \ - } \ - } \ - __cu_len; \ -}) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) +{ + if (eva_kernel_access()) + return __invoke_copy_from_kernel(to, from, n); + else + return __invoke_copy_from_user(to, from, n); +} -#define __copy_in_user(to, from, n) \ -({ \ - void __user *__cu_to; \ - const void __user *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - if (eva_kernel_access()) { \ - __cu_len = ___invoke_copy_in_kernel(__cu_to, __cu_from, \ - __cu_len); \ - } else { \ - might_fault(); \ - __cu_len = ___invoke_copy_in_user(__cu_to, __cu_from, \ - __cu_len); \ - } \ - __cu_len; \ -}) +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER -#define copy_in_user(to, from, n) \ -({ \ - void __user *__cu_to; \ - const void __user *__cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - if (eva_kernel_access()) { \ - __cu_len = ___invoke_copy_in_kernel(__cu_to,__cu_from, \ - __cu_len); \ - } else { \ - if (likely(access_ok(VERIFY_READ, __cu_from, __cu_len) &&\ - access_ok(VERIFY_WRITE, __cu_to, __cu_len))) {\ - might_fault(); \ - __cu_len = ___invoke_copy_in_user(__cu_to, \ - __cu_from, \ - __cu_len); \ - } \ - } \ - __cu_len; \ -}) +static inline unsigned long +raw_copy_in_user(void __user*to, const void __user *from, unsigned long n) +{ + if (eva_kernel_access()) + return ___invoke_copy_in_kernel(to, from, n); + else + return ___invoke_copy_in_user(to, from, n); +} extern __kernel_size_t __bzero_kernel(void __user *addr, __kernel_size_t size); extern __kernel_size_t __bzero(void __user *addr, __kernel_size_t size); diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 566ecdcb5b4b..3418ec9c1c50 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -110,4 +110,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h index 3e940dbe0262..78faf4292e90 100644 --- a/arch/mips/include/uapi/asm/unistd.h +++ b/arch/mips/include/uapi/asm/unistd.h @@ -386,17 +386,18 @@ #define __NR_pkey_mprotect (__NR_Linux + 363) #define __NR_pkey_alloc (__NR_Linux + 364) #define __NR_pkey_free (__NR_Linux + 365) +#define __NR_statx (__NR_Linux + 366) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 365 +#define __NR_Linux_syscalls 366 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 365 +#define __NR_O32_Linux_syscalls 366 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -730,16 +731,17 @@ #define __NR_pkey_mprotect (__NR_Linux + 323) #define __NR_pkey_alloc (__NR_Linux + 324) #define __NR_pkey_free (__NR_Linux + 325) +#define __NR_statx (__NR_Linux + 326) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 325 +#define __NR_Linux_syscalls 326 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 325 +#define __NR_64_Linux_syscalls 326 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -1077,15 +1079,16 @@ #define __NR_pkey_mprotect (__NR_Linux + 327) #define __NR_pkey_alloc (__NR_Linux + 328) #define __NR_pkey_free (__NR_Linux + 329) +#define __NR_statx (__NR_Linux + 330) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 329 +#define __NR_Linux_syscalls 330 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 329 +#define __NR_N32_Linux_syscalls 330 #endif /* _UAPI_ASM_UNISTD_H */ diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c index bcf8f8c62737..bb1ad5119da4 100644 --- a/arch/mips/jz4740/time.c +++ b/arch/mips/jz4740/time.c @@ -145,7 +145,9 @@ void __init plat_time_init(void) clockevent_set_clock(&jz4740_clockevent, clk_rate); jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent); + jz4740_clockevent.min_delta_ticks = 100; jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent); + jz4740_clockevent.max_delta_ticks = 0xffff; jz4740_clockevent.cpumask = cpumask_of(0); clockevents_register_device(&jz4740_clockevent); diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index bb5c5d34ba81..a670c0c11875 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -102,6 +102,7 @@ void output_thread_info_defines(void) DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_MASK, THREAD_MASK); DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); + DEFINE(_IRQ_STACK_START, IRQ_STACK_START); BLANK(); } diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 940ac00e9129..8f9f2daf06a3 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -123,7 +123,9 @@ void sb1480_clockevent_init(void) CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); + cd->max_delta_ticks = 0x7fffff; cd->min_delta_ns = clockevent_delta2ns(2, cd); + cd->min_delta_ticks = 2; cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of(cpu); diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index 77a5ddf53f57..61ad9079fa16 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -128,7 +128,9 @@ int __init ds1287_clockevent_init(int irq) cd->irq = irq; clockevent_set_clock(cd, 32768); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ticks = 0x300; cd->cpumask = cpumask_of(0); clockevents_register_device(&ds1287_clockevent); diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index 66040051151d..fd90c82dc17d 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -152,7 +152,9 @@ static int __init gt641xx_timer0_clockevent_init(void) cd->rating = 200 + gt641xx_base_clock / 10000000; clockevent_set_clock(cd, gt641xx_base_clock); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ticks = 0x300; cd->cpumask = cpumask_of(0); clockevents_register_device(>641xx_timer0_clockevent); diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 804d2a2a19fe..dd6a18bc10ab 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -80,7 +80,7 @@ static unsigned int calculate_min_delta(void) } /* Sorted insert of 75th percentile into buf2 */ - for (k = 0; k < i; ++k) { + for (k = 0; k < i && k < ARRAY_SIZE(buf2); ++k) { if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) { l = min_t(unsigned int, i, ARRAY_SIZE(buf2) - 1); diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index 3d860efd63b9..9d1edb5938b8 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -123,7 +123,9 @@ void sb1250_clockevent_init(void) CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); + cd->max_delta_ticks = 0x7fffff; cd->min_delta_ns = clockevent_delta2ns(2, cd); + cd->min_delta_ticks = 2; cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of(cpu); diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index aaca60d6ffc3..7b17c8f5009d 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c @@ -196,7 +196,9 @@ void __init txx9_clockevent_init(unsigned long baseaddr, int irq, clockevent_set_clock(cd, TIMER_CLK(imbusclk)); cd->max_delta_ns = clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd); + cd->max_delta_ticks = 0xffffffff >> (32 - TXX9_TIMER_BITS); cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + cd->min_delta_ticks = 0xf; cd->irq = irq; cd->cpumask = cpumask_of(0), clockevents_register_device(cd); diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 59476a607add..a00e87b0256d 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -361,7 +361,7 @@ LEAF(mips_cps_get_bootcfg) END(mips_cps_get_bootcfg) LEAF(mips_cps_boot_vpes) - PTR_L ta2, COREBOOTCFG_VPEMASK(a0) + lw ta2, COREBOOTCFG_VPEMASK(a0) PTR_L ta3, COREBOOTCFG_VPECONFIG(a0) #if defined(CONFIG_CPU_MIPSR6) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 07718bb5fc9d..12422fd4af23 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1824,7 +1824,7 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) } decode_configs(c); - c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; + c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; c->writecombine = _CACHE_UNCACHED_ACCELERATED; break; default: diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c index 6430bff21fff..5c429d70e17f 100644 --- a/arch/mips/kernel/elf.c +++ b/arch/mips/kernel/elf.c @@ -257,7 +257,7 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr, else if ((prog_req.fr1 && prog_req.frdefault) || (prog_req.single && !prog_req.frdefault)) /* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */ - state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) && + state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) && cpu_has_mips_r2_r6) ? FP_FR1 : FP_FR0; else if (prog_req.fr1) diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 7ec9612cb007..ae810da4d499 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -215,9 +215,11 @@ NESTED(handle_int, PT_SIZE, sp) beq t0, t1, 2f /* Switch to IRQ stack */ - li t1, _IRQ_STACK_SIZE + li t1, _IRQ_STACK_START PTR_ADD sp, t0, t1 + /* Save task's sp on IRQ stack so that unwinding can follow it */ + LONG_S s1, 0(sp) 2: jal plat_irq_dispatch @@ -325,9 +327,11 @@ NESTED(except_vec_vi_handler, 0, sp) beq t0, t1, 2f /* Switch to IRQ stack */ - li t1, _IRQ_STACK_SIZE + li t1, _IRQ_STACK_START PTR_ADD sp, t0, t1 + /* Save task's sp on IRQ stack so that unwinding can follow it */ + LONG_S s1, 0(sp) 2: jalr v0 @@ -519,7 +523,7 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER reserved reserved sti verbose /* others */ .align 5 - LEAF(handle_ri_rdhwr_vivt) + LEAF(handle_ri_rdhwr_tlbp) .set push .set noat .set noreorder @@ -538,7 +542,7 @@ NESTED(nmi_handler, PT_SIZE, sp) .set pop bltz k1, handle_ri /* slow path */ /* fall thru */ - END(handle_ri_rdhwr_vivt) + END(handle_ri_rdhwr_tlbp) LEAF(handle_ri_rdhwr) .set push diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 1f4bd222ba76..eb6c0d582626 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -244,9 +244,6 @@ static int compute_signal(int tt) void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) { int reg; - struct thread_info *ti = task_thread_info(p); - unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32; - struct pt_regs *regs = (struct pt_regs *)ksp - 1; #if (KGDB_GDB_REG_SIZE == 32) u32 *ptr = (u32 *)gdb_regs; #else @@ -254,25 +251,46 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) #endif for (reg = 0; reg < 16; reg++) - *(ptr++) = regs->regs[reg]; + *(ptr++) = 0; /* S0 - S7 */ - for (reg = 16; reg < 24; reg++) - *(ptr++) = regs->regs[reg]; + *(ptr++) = p->thread.reg16; + *(ptr++) = p->thread.reg17; + *(ptr++) = p->thread.reg18; + *(ptr++) = p->thread.reg19; + *(ptr++) = p->thread.reg20; + *(ptr++) = p->thread.reg21; + *(ptr++) = p->thread.reg22; + *(ptr++) = p->thread.reg23; for (reg = 24; reg < 28; reg++) *(ptr++) = 0; /* GP, SP, FP, RA */ - for (reg = 28; reg < 32; reg++) - *(ptr++) = regs->regs[reg]; - - *(ptr++) = regs->cp0_status; - *(ptr++) = regs->lo; - *(ptr++) = regs->hi; - *(ptr++) = regs->cp0_badvaddr; - *(ptr++) = regs->cp0_cause; - *(ptr++) = regs->cp0_epc; + *(ptr++) = (long)p; + *(ptr++) = p->thread.reg29; + *(ptr++) = p->thread.reg30; + *(ptr++) = p->thread.reg31; + + *(ptr++) = p->thread.cp0_status; + + /* lo, hi */ + *(ptr++) = 0; + *(ptr++) = 0; + + /* + * BadVAddr, Cause + * Ideally these would come from the last exception frame up the stack + * but that requires unwinding, otherwise we can't know much for sure. + */ + *(ptr++) = 0; + *(ptr++) = 0; + + /* + * PC + * use return address (RA), i.e. the moment after return from resume() + */ + *(ptr++) = p->thread.reg31; } void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index d8f1cf1ec370..550e7d03090a 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -1200,7 +1200,7 @@ fpu_emul: case lwl_op: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_READ, vaddr, 4)) { + if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1273,7 +1273,7 @@ fpu_emul: case lwr_op: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_READ, vaddr, 4)) { + if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1347,7 +1347,7 @@ fpu_emul: case swl_op: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_WRITE, vaddr, 4)) { + if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1417,7 +1417,7 @@ fpu_emul: case swr_op: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_WRITE, vaddr, 4)) { + if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1492,7 +1492,7 @@ fpu_emul: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_READ, vaddr, 8)) { + if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1611,7 +1611,7 @@ fpu_emul: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_READ, vaddr, 8)) { + if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1730,7 +1730,7 @@ fpu_emul: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_WRITE, vaddr, 8)) { + if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1848,7 +1848,7 @@ fpu_emul: rt = regs->regs[MIPSInst_RT(inst)]; vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); - if (!access_ok(VERIFY_WRITE, vaddr, 8)) { + if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) { current->thread.cp0_baduaddr = vaddr; err = SIGSEGV; break; @@ -1965,7 +1965,7 @@ fpu_emul: err = SIGBUS; break; } - if (!access_ok(VERIFY_READ, vaddr, 4)) { + if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) { current->thread.cp0_baduaddr = vaddr; err = SIGBUS; break; @@ -2021,7 +2021,7 @@ fpu_emul: err = SIGBUS; break; } - if (!access_ok(VERIFY_WRITE, vaddr, 4)) { + if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) { current->thread.cp0_baduaddr = vaddr; err = SIGBUS; break; @@ -2084,7 +2084,7 @@ fpu_emul: err = SIGBUS; break; } - if (!access_ok(VERIFY_READ, vaddr, 8)) { + if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) { current->thread.cp0_baduaddr = vaddr; err = SIGBUS; break; @@ -2145,7 +2145,7 @@ fpu_emul: err = SIGBUS; break; } - if (!access_ok(VERIFY_WRITE, vaddr, 8)) { + if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) { current->thread.cp0_baduaddr = vaddr; err = SIGBUS; break; diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 8c35b3152e1e..9452b02ce079 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1446,6 +1446,11 @@ static int mipsxx_pmu_handle_shared_irq(void) HANDLE_COUNTER(0) } +#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS + read_unlock(&pmuint_rwlock); +#endif + resume_local_counters(); + /* * Do all the work for the pending perf events. We can do this * in here because the performance counter interrupt is a regular @@ -1454,10 +1459,6 @@ static int mipsxx_pmu_handle_shared_irq(void) if (handled == IRQ_HANDLED) irq_work_run(); -#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS - read_unlock(&pmuint_rwlock); -#endif - resume_local_counters(); return handled; } diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index fb6b6b650719..b68e10fc453d 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -488,31 +488,52 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, unsigned long pc, unsigned long *ra) { + unsigned long low, high, irq_stack_high; struct mips_frame_info info; unsigned long size, ofs; + struct pt_regs *regs; int leaf; - extern void ret_from_irq(void); - extern void ret_from_exception(void); if (!stack_page) return 0; /* - * If we reached the bottom of interrupt context, - * return saved pc in pt_regs. + * IRQ stacks start at IRQ_STACK_START + * task stacks at THREAD_SIZE - 32 */ - if (pc == (unsigned long)ret_from_irq || - pc == (unsigned long)ret_from_exception) { - struct pt_regs *regs; - if (*sp >= stack_page && - *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) { - regs = (struct pt_regs *)*sp; - pc = regs->cp0_epc; - if (!user_mode(regs) && __kernel_text_address(pc)) { - *sp = regs->regs[29]; - *ra = regs->regs[31]; - return pc; - } + low = stack_page; + if (!preemptible() && on_irq_stack(raw_smp_processor_id(), *sp)) { + high = stack_page + IRQ_STACK_START; + irq_stack_high = high; + } else { + high = stack_page + THREAD_SIZE - 32; + irq_stack_high = 0; + } + + /* + * If we reached the top of the interrupt stack, start unwinding + * the interrupted task stack. + */ + if (unlikely(*sp == irq_stack_high)) { + unsigned long task_sp = *(unsigned long *)*sp; + + /* + * Check that the pointer saved in the IRQ stack head points to + * something within the stack of the current task + */ + if (!object_is_on_stack((void *)task_sp)) + return 0; + + /* + * Follow pointer to tasks kernel stack frame where interrupted + * state was saved. + */ + regs = (struct pt_regs *)task_sp; + pc = regs->cp0_epc; + if (!user_mode(regs) && __kernel_text_address(pc)) { + *sp = regs->regs[29]; + *ra = regs->regs[31]; + return pc; } return 0; } @@ -533,8 +554,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, if (leaf < 0) return 0; - if (*sp < stack_page || - *sp + info.frame_size > stack_page + THREAD_SIZE - 32) + if (*sp < low || *sp + info.frame_size > high) return 0; if (leaf) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 339601267265..6931fe722a0b 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -456,7 +456,8 @@ static int fpr_set(struct task_struct *target, &target->thread.fpu, 0, sizeof(elf_fpregset_t)); - for (i = 0; i < NUM_FPU_REGS; i++) { + BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t)); + for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) { err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fpr_val, i * sizeof(elf_fpreg_t), (i + 1) * sizeof(elf_fpreg_t)); diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index 9103bebc9a8e..2d1a0c438771 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -18,7 +18,7 @@ #include <linux/kernel.h> #include <linux/libfdt.h> #include <linux/of_fdt.h> -#include <linux/sched.h> +#include <linux/sched/task.h> #include <linux/start_kernel.h> #include <linux/string.h> #include <linux/printk.h> diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index c29d397eee86..80ed68b2c95e 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -600,3 +600,4 @@ EXPORT(sys_call_table) PTR sys_pkey_mprotect PTR sys_pkey_alloc PTR sys_pkey_free /* 4365 */ + PTR sys_statx diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 0687f96ee912..49765b44aa9b 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -438,4 +438,5 @@ EXPORT(sys_call_table) PTR sys_pkey_mprotect PTR sys_pkey_alloc PTR sys_pkey_free /* 5325 */ + PTR sys_statx .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 0331ba39a065..90bad2d1b2d3 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -433,4 +433,5 @@ EXPORT(sysn32_call_table) PTR sys_pkey_mprotect PTR sys_pkey_alloc PTR sys_pkey_free + PTR sys_statx /* 6330 */ .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 5a47042dd25f..2dd70bd104e1 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -588,4 +588,5 @@ EXPORT(sys32_call_table) PTR sys_pkey_mprotect PTR sys_pkey_alloc PTR sys_pkey_free /* 4365 */ + PTR sys_statx .size sys32_call_table,.-sys32_call_table diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 3daa2cae50b0..1b070a76fcdd 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -11,6 +11,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/sched/hotplug.h> +#include <linux/sched/task_stack.h> #include <linux/mm.h> #include <linux/delay.h> #include <linux/smp.h> diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 6d45f05538c8..795b4aaf8927 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -422,13 +422,12 @@ void play_dead(void) local_irq_disable(); idle_task_exit(); cpu = smp_processor_id(); + core = cpu_data[cpu].core; cpu_death = CPU_DEATH_POWER; pr_debug("CPU%d going offline\n", cpu); if (cpu_has_mipsmt || cpu_has_vp) { - core = cpu_data[cpu].core; - /* Look for another online VPE within the core */ for_each_online_cpu(cpu_death_sibling) { if (cpu_data[cpu_death_sibling].core != core) diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index e077ea3e11fb..e398cbc3d776 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/irqchip/mips-gic.h> #include <linux/compiler.h> +#include <linux/sched/task_stack.h> #include <linux/smp.h> #include <linux/atomic.h> diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index f1d17ece4181..1dfa7f5796c7 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -98,7 +98,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) if (unlikely(addr & 3)) return -EINVAL; - if (unlikely(!access_ok(VERIFY_WRITE, addr, 4))) + if (unlikely(!access_ok(VERIFY_WRITE, (const void __user *)addr, 4))) return -EINVAL; if (cpu_has_llsc && R10000_LLSC_WAR) { diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c7d17cfb32f6..b49e7bf9f950 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -83,7 +83,7 @@ extern asmlinkage void handle_dbe(void); extern asmlinkage void handle_sys(void); extern asmlinkage void handle_bp(void); extern asmlinkage void handle_ri(void); -extern asmlinkage void handle_ri_rdhwr_vivt(void); +extern asmlinkage void handle_ri_rdhwr_tlbp(void); extern asmlinkage void handle_ri_rdhwr(void); extern asmlinkage void handle_cpu(void); extern asmlinkage void handle_ov(void); @@ -2408,9 +2408,18 @@ void __init trap_init(void) set_except_vector(EXCCODE_SYS, handle_sys); set_except_vector(EXCCODE_BP, handle_bp); - set_except_vector(EXCCODE_RI, rdhwr_noopt ? handle_ri : - (cpu_has_vtag_icache ? - handle_ri_rdhwr_vivt : handle_ri_rdhwr)); + + if (rdhwr_noopt) + set_except_vector(EXCCODE_RI, handle_ri); + else { + if (cpu_has_vtag_icache) + set_except_vector(EXCCODE_RI, handle_ri_rdhwr_tlbp); + else if (current_cpu_type() == CPU_LOONGSON3) + set_except_vector(EXCCODE_RI, handle_ri_rdhwr_tlbp); + else + set_except_vector(EXCCODE_RI, handle_ri_rdhwr); + } + set_except_vector(EXCCODE_CPU, handle_cpu); set_except_vector(EXCCODE_OV, handle_ov); set_except_vector(EXCCODE_TR, handle_tr); diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 7ed98354fe9d..f806ee56e639 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -1026,7 +1026,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, goto sigbus; if (IS_ENABLED(CONFIG_EVA)) { - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) LoadHW(addr, value, res); else LoadHWE(addr, value, res); @@ -1045,7 +1045,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, goto sigbus; if (IS_ENABLED(CONFIG_EVA)) { - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) LoadW(addr, value, res); else LoadWE(addr, value, res); @@ -1064,7 +1064,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, goto sigbus; if (IS_ENABLED(CONFIG_EVA)) { - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) LoadHWU(addr, value, res); else LoadHWUE(addr, value, res); @@ -1132,7 +1132,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, value = regs->regs[insn.i_format.rt]; if (IS_ENABLED(CONFIG_EVA)) { - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) StoreHW(addr, value, res); else StoreHWE(addr, value, res); @@ -1152,7 +1152,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, value = regs->regs[insn.i_format.rt]; if (IS_ENABLED(CONFIG_EVA)) { - if (segment_eq(get_fs(), get_ds())) + if (uaccess_kernel()) StoreW(addr, value, res); else StoreWE(addr, value, res); diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index f0a0e6d62be3..8ca2371aa684 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -97,6 +97,7 @@ SECTIONS DATA_DATA CONSTRUCTORS } + BUG_TABLE _gp = . + 0x8000; .lit8 : { *(.lit8) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 3c3aa05891dd..95bec460b651 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -467,7 +467,7 @@ void __init ltq_soc_init(void) if (!np_xbar) panic("Failed to load xbar nodes from devicetree"); - if (of_address_to_resource(np_pmu, 0, &res_xbar)) + if (of_address_to_resource(np_xbar, 0, &res_xbar)) panic("Failed to get xbar resources"); if (!request_mem_region(res_xbar.start, resource_size(&res_xbar), res_xbar.name)) diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index c3031f18c572..3114a2ed1f4e 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S @@ -562,39 +562,9 @@ LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address nop SUB len, AT, t0 # len number of uncopied bytes - bnez t6, .Ldone\@ /* Skip the zeroing part if inatomic */ - /* - * Here's where we rely on src and dst being incremented in tandem, - * See (3) above. - * dst += (fault addr - src) to put dst at first byte to clear - */ - ADD dst, t0 # compute start address in a1 - SUB dst, src - /* - * Clear len bytes starting at dst. Can't call __bzero because it - * might modify len. An inefficient loop for these rare times... - */ - .set reorder /* DADDI_WAR */ - SUB src, len, 1 - beqz len, .Ldone\@ - .set noreorder -1: sb zero, 0(dst) - ADD dst, dst, 1 -#ifndef CONFIG_CPU_DADDI_WORKAROUNDS - bnez src, 1b - SUB src, src, 1 -#else - .set push - .set noat - li v1, 1 - bnez src, 1b - SUB src, src, v1 - .set pop -#endif jr ra nop - #define SEXC(n) \ .set reorder; /* DADDI_WAR */ \ .Ls_exc_p ## n ## u\@: \ @@ -673,15 +643,6 @@ LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ END(__rmemcpy) /* - * t6 is used as a flag to note inatomic mode. - */ -LEAF(__copy_user_inatomic) -EXPORT_SYMBOL(__copy_user_inatomic) - b __copy_user_common - li t6, 1 - END(__copy_user_inatomic) - -/* * A combined memcpy/__copy_user * __copy_user sets len to 0 for success; else to an upper bound of * the number of uncopied bytes. @@ -694,8 +655,6 @@ EXPORT_SYMBOL(memcpy) .L__memcpy: FEXPORT(__copy_user) EXPORT_SYMBOL(__copy_user) - li t6, 0 /* not inatomic */ -__copy_user_common: /* Legacy Mode, user <-> user */ __BUILD_COPY_USER LEGACY_MODE USEROP USEROP @@ -708,20 +667,12 @@ __copy_user_common: * space */ -LEAF(__copy_user_inatomic_eva) -EXPORT_SYMBOL(__copy_user_inatomic_eva) - b __copy_from_user_common - li t6, 1 - END(__copy_user_inatomic_eva) - /* * __copy_from_user (EVA) */ LEAF(__copy_from_user_eva) EXPORT_SYMBOL(__copy_from_user_eva) - li t6, 0 /* not inatomic */ -__copy_from_user_common: __BUILD_COPY_USER EVA_MODE USEROP KERNELOP END(__copy_from_user_eva) diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index e6f972d35252..1c4332a26cf1 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -199,7 +199,9 @@ static void __init ls1x_time_init(void) clockevent_set_clock(cd, mips_hpt_frequency); cd->max_delta_ns = clockevent_delta2ns(0xffffff, cd); + cd->max_delta_ticks = 0xffffff; cd->min_delta_ns = clockevent_delta2ns(0x000300, cd); + cd->min_delta_ticks = 0x000300; cd->cpumask = cpumask_of(smp_processor_id()); clockevents_register_device(cd); diff --git a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index b817d6d3a060..a6adcc4f8960 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c @@ -123,7 +123,9 @@ void __init setup_mfgpt0_timer(void) cd->cpumask = cpumask_of(cpu); clockevent_set_clock(cd, MFGPT_TICK_RATE); cd->max_delta_ns = clockevent_delta2ns(0xffff, cd); + cd->max_delta_ticks = 0xffff; cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + cd->min_delta_ticks = 0xf; /* Enable MFGPT0 Comparator 2 Output to the Interrupt Mapper */ _wrmsr(DIVIL_MSR_REG(MFGPT_IRQ), 0, 0x100); diff --git a/arch/mips/loongson64/loongson-3/cop2-ex.c b/arch/mips/loongson64/loongson-3/cop2-ex.c index ea13764d0a03..621d6af5f6eb 100644 --- a/arch/mips/loongson64/loongson-3/cop2-ex.c +++ b/arch/mips/loongson64/loongson-3/cop2-ex.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/notifier.h> +#include <linux/ptrace.h> #include <asm/fpu.h> #include <asm/cop2.h> diff --git a/arch/mips/loongson64/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c index 24afe364637b..4df9d4b7356a 100644 --- a/arch/mips/loongson64/loongson-3/hpet.c +++ b/arch/mips/loongson64/loongson-3/hpet.c @@ -241,7 +241,9 @@ void __init setup_hpet_timer(void) cd->cpumask = cpumask_of(cpu); clockevent_set_clock(cd, HPET_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd); + cd->min_delta_ticks = HPET_MIN_PROG_DELTA; clockevents_register_device(cd); setup_irq(HPET_T0_IRQ, &hpet_irq); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index e7f798d55fbc..3fe99cb271a9 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1562,6 +1562,7 @@ static void probe_vcache(void) vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz; c->vcache.waybit = 0; + c->vcache.waysize = vcache_size / c->vcache.ways; pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n", vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz); @@ -1664,6 +1665,7 @@ static void __init loongson3_sc_init(void) /* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */ scache_size *= 4; c->scache.waybit = 0; + c->scache.waysize = scache_size / c->scache.ways; pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n", scache_size >> 10, way_string[c->scache.ways], c->scache.linesz); if (scache_size) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 9bfee8988eaf..4f642e07c2b1 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -760,7 +760,8 @@ static void build_huge_update_entries(u32 **p, unsigned int pte, static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r, struct uasm_label **l, unsigned int pte, - unsigned int ptr) + unsigned int ptr, + unsigned int flush) { #ifdef CONFIG_SMP UASM_i_SC(p, pte, 0, ptr); @@ -769,6 +770,22 @@ static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r, #else UASM_i_SW(p, pte, 0, ptr); #endif + if (cpu_has_ftlb && flush) { + BUG_ON(!cpu_has_tlbinv); + + UASM_i_MFC0(p, ptr, C0_ENTRYHI); + uasm_i_ori(p, ptr, ptr, MIPS_ENTRYHI_EHINV); + UASM_i_MTC0(p, ptr, C0_ENTRYHI); + build_tlb_write_entry(p, l, r, tlb_indexed); + + uasm_i_xori(p, ptr, ptr, MIPS_ENTRYHI_EHINV); + UASM_i_MTC0(p, ptr, C0_ENTRYHI); + build_huge_update_entries(p, pte, ptr); + build_huge_tlb_write_entry(p, l, r, pte, tlb_random, 0); + + return; + } + build_huge_update_entries(p, pte, ptr); build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0); } @@ -2199,7 +2216,7 @@ static void build_r4000_tlb_load_handler(void) uasm_l_tlbl_goaround2(&l, p); } uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID)); - build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2); + build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1); #endif uasm_l_nopage_tlbl(&l, p); @@ -2254,7 +2271,7 @@ static void build_r4000_tlb_store_handler(void) build_tlb_probe_entry(&p); uasm_i_ori(&p, wr.r1, wr.r1, _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); - build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2); + build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1); #endif uasm_l_nopage_tlbs(&l, p); @@ -2310,7 +2327,7 @@ static void build_r4000_tlb_modify_handler(void) build_tlb_probe_entry(&p); uasm_i_ori(&p, wr.r1, wr.r1, _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); - build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2); + build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 0); #endif uasm_l_nopage_tlbm(&l, p); diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index cb675ec6f283..54f56d5a96c4 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -232,6 +232,17 @@ void __init arch_init_irq(void) { int corehi_irq; + /* + * Preallocate the i8259's expected virq's here. Since irqchip_init() + * will probe the irqchips in hierarchial order, i8259 is probed last. + * If anything allocates a virq before the i8259 is probed, it will + * be given one of the i8259's expected range and consequently setup + * of the i8259 will fail. + */ + WARN(irq_alloc_descs(I8259A_IRQ_BASE, I8259A_IRQ_BASE, + 16, numa_node_id()) < 0, + "Cannot reserve i8259 virqs at IRQ%d\n", I8259A_IRQ_BASE); + i8259_set_poll(mips_pcibios_iack); irqchip_init(); diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 1829a9031eec..289edcfadd7c 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -21,6 +21,7 @@ #include <linux/i8253.h> #include <linux/init.h> #include <linux/kernel_stat.h> +#include <linux/libfdt.h> #include <linux/math64.h> #include <linux/sched.h> #include <linux/spinlock.h> @@ -207,6 +208,33 @@ static void __init init_rtc(void) CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL); } +#ifdef CONFIG_CLKSRC_MIPS_GIC +static u32 gic_frequency_dt; + +static struct property gic_frequency_prop = { + .name = "clock-frequency", + .length = sizeof(u32), + .value = &gic_frequency_dt, +}; + +static void update_gic_frequency_dt(void) +{ + struct device_node *node; + + gic_frequency_dt = cpu_to_be32(gic_frequency); + + node = of_find_compatible_node(NULL, NULL, "mti,gic-timer"); + if (!node) { + pr_err("mti,gic-timer device node not found\n"); + return; + } + + if (of_update_property(node, &gic_frequency_prop) < 0) + pr_err("error updating gic frequency property\n"); +} + +#endif + void __init plat_time_init(void) { unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK); @@ -236,7 +264,8 @@ void __init plat_time_init(void) printk("GIC frequency %d.%02d MHz\n", freq/1000000, (freq%1000000)*100/1000000); #ifdef CONFIG_CLKSRC_MIPS_GIC - gic_clocksource_init(gic_frequency); + update_gic_frequency_dt(); + clocksource_probe(); #endif } #endif diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index 10d86d54880a..bddf1ef553a4 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -35,6 +35,7 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/sched/task_stack.h> #include <linux/smp.h> #include <linux/irq.h> diff --git a/arch/mips/netlogic/xlp/cop2-ex.c b/arch/mips/netlogic/xlp/cop2-ex.c index 52bc5de42005..21e439b3db70 100644 --- a/arch/mips/netlogic/xlp/cop2-ex.c +++ b/arch/mips/netlogic/xlp/cop2-ex.c @@ -9,11 +9,14 @@ * Copyright (C) 2009 Wind River Systems, * written by Ralf Baechle <ralf@linux-mips.org> */ +#include <linux/capability.h> #include <linux/init.h> #include <linux/irqflags.h> #include <linux/notifier.h> #include <linux/prefetch.h> +#include <linux/ptrace.h> #include <linux/sched.h> +#include <linux/sched/task_stack.h> #include <asm/cop2.h> #include <asm/current.h> diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c index 5e645c9a3162..16ace558cd9d 100644 --- a/arch/mips/oprofile/backtrace.c +++ b/arch/mips/oprofile/backtrace.c @@ -18,7 +18,7 @@ struct stackframe { static inline int get_mem(unsigned long addr, unsigned long *result) { unsigned long *address = (unsigned long *) addr; - if (!access_ok(VERIFY_READ, addr, sizeof(unsigned long))) + if (!access_ok(VERIFY_READ, address, sizeof(unsigned long))) return -1; if (__copy_from_user_inatomic(result, address, sizeof(unsigned long))) return -3; diff --git a/arch/mips/pci/pci-legacy.c b/arch/mips/pci/pci-legacy.c index 014649be158d..3a84f6c0c840 100644 --- a/arch/mips/pci/pci-legacy.c +++ b/arch/mips/pci/pci-legacy.c @@ -190,7 +190,7 @@ void register_pci_controller(struct pci_controller *hose) } INIT_LIST_HEAD(&hose->list); - list_add(&hose->list, &controllers); + list_add_tail(&hose->list, &controllers); /* * Do not panic here but later - this might happen before console init. diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index f24eee04e16a..b8a1376165b0 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -129,7 +129,9 @@ static int __init ralink_systick_init(struct device_node *np) systick.dev.name = np->name; clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); + systick.dev.max_delta_ticks = 0x7fff; systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); + systick.dev.min_delta_ticks = 0x3; systick.dev.irq = irq_of_parse_and_map(np, 0); if (!systick.dev.irq) { pr_err("%s: request_irq failed", np->name); diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index c4ffd43d3996..48ce701557a4 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -35,7 +35,7 @@ static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; -static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) }; +static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) }; static struct rt2880_pmx_func pci_func[] = { FUNC("pci-dev", 0, 40, 32), FUNC("pci-host2", 1, 40, 32), @@ -43,7 +43,7 @@ static struct rt2880_pmx_func pci_func[] = { FUNC("pci-fnc", 3, 40, 32) }; static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) }; -static struct rt2880_pmx_func ge2_func[] = { FUNC("ge1", 0, 84, 12) }; +static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) }; static struct rt2880_pmx_group rt3883_pinmux_data[] = { GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C), diff --git a/arch/mips/sgi-ip22/ip28-berr.c b/arch/mips/sgi-ip22/ip28-berr.c index 1f2a5bc4779e..75460e1e106b 100644 --- a/arch/mips/sgi-ip22/ip28-berr.c +++ b/arch/mips/sgi-ip22/ip28-berr.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/sched/debug.h> +#include <linux/sched/signal.h> #include <linux/seq_file.h> #include <asm/addrspace.h> diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c index d12879eb2b1f..83efe03d5c60 100644 --- a/arch/mips/sgi-ip27/ip27-berr.c +++ b/arch/mips/sgi-ip27/ip27-berr.c @@ -12,7 +12,9 @@ #include <linux/signal.h> /* for SIGBUS */ #include <linux/sched.h> /* schow_regs(), force_sig() */ #include <linux/sched/debug.h> +#include <linux/sched/signal.h> +#include <asm/ptrace.h> #include <asm/sn/addrs.h> #include <asm/sn/arch.h> #include <asm/sn/sn0/hub.h> diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index f5ed45e8f442..4cd47d23d81a 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -8,10 +8,13 @@ */ #include <linux/init.h> #include <linux/sched.h> +#include <linux/sched/task_stack.h> #include <linux/topology.h> #include <linux/nodemask.h> + #include <asm/page.h> #include <asm/processor.h> +#include <asm/ptrace.h> #include <asm/sn/arch.h> #include <asm/sn/gda.h> #include <asm/sn/intr.h> diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 695c51bdd7dc..a53f0c8c901e 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -113,7 +113,9 @@ void hub_rt_clock_event_init(void) cd->features = CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, CYCLES_PER_SEC); cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); + cd->max_delta_ticks = 0xfffffffffffff; cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ticks = 0x300; cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of(cpu); diff --git a/arch/mips/sgi-ip32/ip32-berr.c b/arch/mips/sgi-ip32/ip32-berr.c index 57d8c7486fe6..c1f12a9cf305 100644 --- a/arch/mips/sgi-ip32/ip32-berr.c +++ b/arch/mips/sgi-ip32/ip32-berr.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/sched/debug.h> +#include <linux/sched/signal.h> #include <asm/traps.h> #include <linux/uaccess.h> #include <asm/addrspace.h> diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 8bd415c8729f..b3b442def423 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> +#include <linux/sched/signal.h> #include <linux/notifier.h> #include <linux/delay.h> #include <linux/rtc/ds1685.h> diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index 97f64c723a0c..ed810e7206e8 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@ -2,6 +2,7 @@ generic-y += barrier.h generic-y += clkdev.h generic-y += exec.h +generic-y += extable.h generic-y += irq_work.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h diff --git a/arch/mn10300/include/asm/page.h b/arch/mn10300/include/asm/page.h index 3810a6f740fd..dfe730a5ede0 100644 --- a/arch/mn10300/include/asm/page.h +++ b/arch/mn10300/include/asm/page.h @@ -57,6 +57,7 @@ typedef struct page *pgtable_t; #define __pgd(x) ((pgd_t) { (x) }) #define __pgprot(x) ((pgprot_t) { (x) }) +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #endif /* !__ASSEMBLY__ */ diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 2eedf6f46a57..c6966474827f 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h @@ -14,13 +14,8 @@ /* * User space memory access functions */ -#include <linux/thread_info.h> #include <linux/kernel.h> #include <asm/page.h> -#include <asm/errno.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 /* * The fs value determines whether argument validity checking should be @@ -71,26 +66,7 @@ static inline int ___range_ok(unsigned long addr, unsigned int size) #define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0) #define __access_ok(addr, size) (__range_ok((addr), (size)) == 0) -/* - * 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 int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> #define put_user(x, ptr) __put_user_check((x), (ptr), sizeof(*(ptr))) #define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr))) @@ -299,170 +275,19 @@ do { \ } \ } while (0) -#define __copy_user_zeroing(to, from, size) \ -do { \ - if (size) { \ - void *__to = to; \ - const void *__from = from; \ - int w; \ - asm volatile( \ - "0: movbu (%0),%3;\n" \ - "1: movbu %3,(%1);\n" \ - " inc %0;\n" \ - " inc %1;\n" \ - " add -1,%2;\n" \ - " bne 0b;\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - "3:\n" \ - " mov %2,%0\n" \ - " clr %3\n" \ - "4: movbu %3,(%1);\n" \ - " inc %1;\n" \ - " add -1,%2;\n" \ - " bne 4b;\n" \ - " mov %0,%2\n" \ - " jmp 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .balign 4\n" \ - " .long 0b,3b\n" \ - " .long 1b,3b\n" \ - " .previous\n" \ - : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\ - : "0"(__from), "1"(__to), "2"(size) \ - : "cc", "memory"); \ - } \ -} while (0) - -/* We let the __ versions of copy_from/to_user inline, because they're often - * used in fast paths and have only a small space overhead. - */ -static inline -unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, - unsigned long n) -{ - __copy_user_zeroing(to, from, n); - return n; -} - -static inline -unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, - unsigned long n) +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { __copy_user(to, from, n); return n; } - -#if 0 -#error "don't use - these macros don't increment to & from pointers" -/* Optimize just a little bit when we know the size of the move. */ -#define __constant_copy_user(to, from, size) \ -do { \ - asm volatile( \ - " mov %0,a0;\n" \ - "0: movbu (%1),d3;\n" \ - "1: movbu d3,(%2);\n" \ - " add -1,a0;\n" \ - " bne 0b;\n" \ - "2:;" \ - ".section .fixup,\"ax\"\n" \ - "3: jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .balign 4\n" \ - " .long 0b,3b\n" \ - " .long 1b,3b\n" \ - ".previous" \ - : \ - : "d"(size), "d"(to), "d"(from) \ - : "d3", "a0"); \ -} while (0) - -/* Optimize just a little bit when we know the size of the move. */ -#define __constant_copy_user_zeroing(to, from, size) \ -do { \ - asm volatile( \ - " mov %0,a0;\n" \ - "0: movbu (%1),d3;\n" \ - "1: movbu d3,(%2);\n" \ - " add -1,a0;\n" \ - " bne 0b;\n" \ - "2:;" \ - ".section .fixup,\"ax\"\n" \ - "3: jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .balign 4\n" \ - " .long 0b,3b\n" \ - " .long 1b,3b\n" \ - ".previous" \ - : \ - : "d"(size), "d"(to), "d"(from) \ - : "d3", "a0"); \ -} while (0) - -static inline -unsigned long __constant_copy_to_user(void *to, const void *from, - unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - __constant_copy_user(to, from, n); - return n; -} - -static inline -unsigned long __constant_copy_from_user(void *to, const void *from, - unsigned long n) +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - if (access_ok(VERIFY_READ, from, n)) - __constant_copy_user_zeroing(to, from, n); - return n; -} - -static inline -unsigned long __constant_copy_to_user_nocheck(void *to, const void *from, - unsigned long n) -{ - __constant_copy_user(to, from, n); - return n; -} - -static inline -unsigned long __constant_copy_from_user_nocheck(void *to, const void *from, - unsigned long n) -{ - __constant_copy_user_zeroing(to, from, n); + __copy_user(to, from, n); return n; } -#endif - -extern unsigned long __generic_copy_to_user(void __user *, const void *, - unsigned long); -extern unsigned long __generic_copy_from_user(void *, const void __user *, - unsigned long); - -#define __copy_to_user_inatomic(to, from, n) \ - __generic_copy_to_user_nocheck((to), (from), (n)) -#define __copy_from_user_inatomic(to, from, n) \ - __generic_copy_from_user_nocheck((to), (from), (n)) - -#define __copy_to_user(to, from, n) \ -({ \ - might_fault(); \ - __copy_to_user_inatomic((to), (from), (n)); \ -}) - -#define __copy_from_user(to, from, n) \ -({ \ - might_fault(); \ - __copy_from_user_inatomic((to), (from), (n)); \ -}) - - -#define copy_to_user(to, from, n) __generic_copy_to_user((to), (from), (n)) -#define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n)) extern long strncpy_from_user(char *dst, const char __user *src, long count); extern long __strncpy_from_user(char *dst, const char __user *src, long count); diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h index 0e12527c4b0e..4526e92301a6 100644 --- a/arch/mn10300/include/uapi/asm/socket.h +++ b/arch/mn10300/include/uapi/asm/socket.h @@ -92,4 +92,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index d9b34dd44f04..2b21bbc9efa4 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c @@ -98,7 +98,9 @@ int __init init_clockevents(void) /* Calculate the min / max delta */ cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd); + cd->max_delta_ticks = TMJCBR_MAX; cd->min_delta_ns = clockevent_delta2ns(100, cd); + cd->min_delta_ticks = 100; cd->rating = 200; cd->cpumask = cpumask_of(smp_processor_id()); diff --git a/arch/mn10300/kernel/mn10300_ksyms.c b/arch/mn10300/kernel/mn10300_ksyms.c index ec6c4f8f93a6..5e9f919635f0 100644 --- a/arch/mn10300/kernel/mn10300_ksyms.c +++ b/arch/mn10300/kernel/mn10300_ksyms.c @@ -26,8 +26,6 @@ EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(clear_user); EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(__generic_copy_from_user); -EXPORT_SYMBOL(__generic_copy_to_user); EXPORT_SYMBOL(strnlen_user); extern u64 __ashrdi3(u64, unsigned); diff --git a/arch/mn10300/lib/usercopy.c b/arch/mn10300/lib/usercopy.c index ce8899e5e171..cece1799cc32 100644 --- a/arch/mn10300/lib/usercopy.c +++ b/arch/mn10300/lib/usercopy.c @@ -11,24 +11,6 @@ */ #include <linux/uaccess.h> -unsigned long -__generic_copy_to_user(void *to, const void *from, unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - __copy_user(to, from, n); - return n; -} - -unsigned long -__generic_copy_from_user(void *to, const void *from, unsigned long n) -{ - if (access_ok(VERIFY_READ, from, n)) - __copy_user_zeroing(to, from, n); - else - memset(to, 0, n); - return n; -} - /* * Copy a null terminated string from userspace. */ diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index aaa3c218b56c..87e70f2b463f 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -13,6 +13,7 @@ generic-y += dma.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += ftrace.h diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h index 298393c3cb42..db4f7d179220 100644 --- a/arch/nios2/include/asm/pgtable.h +++ b/arch/nios2/include/asm/pgtable.h @@ -22,6 +22,7 @@ #include <asm/tlbflush.h> #include <asm/pgtable-bits.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #define FIRST_USER_ADDRESS 0UL diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h index 0ab82324c817..727bd9504899 100644 --- a/arch/nios2/include/asm/uaccess.h +++ b/arch/nios2/include/asm/uaccess.h @@ -13,33 +13,11 @@ #ifndef _ASM_NIOS2_UACCESS_H #define _ASM_NIOS2_UACCESS_H -#include <linux/errno.h> -#include <linux/thread_info.h> #include <linux/string.h> #include <asm/page.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * 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; - unsigned long fixup; -}; - -extern int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> /* * Segment stuff @@ -95,36 +73,17 @@ static inline unsigned long __must_check clear_user(void __user *to, return __clear_user(to, n); } -extern long __copy_from_user(void *to, const void __user *from, - unsigned long n); -extern long __copy_to_user(void __user *to, const void *from, unsigned long n); - -static inline long copy_from_user(void *to, const void __user *from, - unsigned long n) -{ - unsigned long res = n; - if (access_ok(VERIFY_READ, from, n)) - res = __copy_from_user(to, from, n); - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; -} - -static inline long copy_to_user(void __user *to, const void *from, - unsigned long n) -{ - if (!access_ok(VERIFY_WRITE, to, n)) - return n; - return __copy_to_user(to, from, n); -} +extern unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n); +extern unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n); +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER extern long strncpy_from_user(char *__to, const char __user *__from, long __len); extern long strnlen_user(const char __user *s, long n); -#define __copy_from_user_inatomic __copy_from_user -#define __copy_to_user_inatomic __copy_to_user - /* Optimized macros */ #define __get_user_asm(val, insn, addr, err) \ { \ diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 367c5426157b..3901b80d4420 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c @@ -48,6 +48,13 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) return alloc_bootmem_align(size, align); } +int __init early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, + bool nomap) +{ + reserve_bootmem(base, size, BOOTMEM_DEFAULT); + return 0; +} + void __init early_init_devtree(void *params) { __be32 *dtb = (u32 *)__dtb_start; diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index 6e57ffa5db27..6044d9be28b4 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c @@ -201,6 +201,9 @@ void __init setup_arch(char **cmdline_p) } #endif /* CONFIG_BLK_DEV_INITRD */ + early_init_fdt_reserve_self(); + early_init_fdt_scan_reserved_mem(); + unflatten_and_copy_device_tree(); setup_cpuinfo(); diff --git a/arch/nios2/mm/uaccess.c b/arch/nios2/mm/uaccess.c index 7663e156ff4f..804983317766 100644 --- a/arch/nios2/mm/uaccess.c +++ b/arch/nios2/mm/uaccess.c @@ -10,9 +10,9 @@ #include <linux/export.h> #include <linux/uaccess.h> -asm(".global __copy_from_user\n" - " .type __copy_from_user, @function\n" - "__copy_from_user:\n" +asm(".global raw_copy_from_user\n" + " .type raw_copy_from_user, @function\n" + "raw_copy_from_user:\n" " movi r2,7\n" " mov r3,r4\n" " bge r2,r6,1f\n" @@ -65,12 +65,12 @@ asm(".global __copy_from_user\n" ".word 7b,13b\n" ".previous\n" ); -EXPORT_SYMBOL(__copy_from_user); +EXPORT_SYMBOL(raw_copy_from_user); asm( - " .global __copy_to_user\n" - " .type __copy_to_user, @function\n" - "__copy_to_user:\n" + " .global raw_copy_to_user\n" + " .type raw_copy_to_user, @function\n" + "raw_copy_to_user:\n" " movi r2,7\n" " mov r3,r4\n" " bge r2,r6,1f\n" @@ -127,7 +127,7 @@ asm( ".word 11b,13b\n" ".word 12b,13b\n" ".previous\n"); -EXPORT_SYMBOL(__copy_to_user); +EXPORT_SYMBOL(raw_copy_to_user); long strncpy_from_user(char *__to, const char __user *__from, long __len) { diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index fb01873a5aad..df8e2f7bc7dd 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -16,6 +16,7 @@ generic-y += dma.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += ftrace.h diff --git a/arch/openrisc/include/asm/cmpxchg.h b/arch/openrisc/include/asm/cmpxchg.h index 5fcb9ac72693..f0a5d8b844d6 100644 --- a/arch/openrisc/include/asm/cmpxchg.h +++ b/arch/openrisc/include/asm/cmpxchg.h @@ -77,7 +77,11 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr, return val; } -#define xchg(ptr, with) \ - ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), sizeof(*(ptr)))) +#define xchg(ptr, with) \ + ({ \ + (__typeof__(*(ptr))) __xchg((unsigned long)(with), \ + (ptr), \ + sizeof(*(ptr))); \ + }) #endif /* __ASM_OPENRISC_CMPXCHG_H */ diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h index 3567aa7be555..ff97374ca069 100644 --- a/arch/openrisc/include/asm/pgtable.h +++ b/arch/openrisc/include/asm/pgtable.h @@ -25,6 +25,7 @@ #ifndef __ASM_OPENRISC_PGTABLE_H #define __ASM_OPENRISC_PGTABLE_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #ifndef __ASSEMBLY__ diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h index 140faa16685a..a557a7cd0232 100644 --- a/arch/openrisc/include/asm/uaccess.h +++ b/arch/openrisc/include/asm/uaccess.h @@ -22,14 +22,10 @@ /* * User space memory access functions */ -#include <linux/errno.h> -#include <linux/thread_info.h> #include <linux/prefetch.h> #include <linux/string.h> #include <asm/page.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 +#include <asm/extable.h> /* * The fs value determines whether argument validity checking should be @@ -66,23 +62,6 @@ __range_ok((unsigned long)addr, (unsigned long)size) /* - * 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; -}; - -/* * These are the main single-value transfer routines. They automatically * use the right size if we just have the right pointer type. * @@ -211,7 +190,7 @@ do { \ case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \ case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \ case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \ - case 8: __get_user_asm2(x, ptr, retval); \ + case 8: __get_user_asm2(x, ptr, retval); break; \ default: (x) = __get_user_bad(); \ } \ } while (0) @@ -257,34 +236,18 @@ do { \ extern unsigned long __must_check __copy_tofrom_user(void *to, const void *from, unsigned long size); - -#define __copy_from_user(to, from, size) \ - __copy_tofrom_user(to, from, size) -#define __copy_to_user(to, from, size) \ - __copy_tofrom_user(to, from, size) - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - static inline unsigned long -copy_from_user(void *to, const void *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long size) { - unsigned long res = n; - - if (likely(access_ok(VERIFY_READ, from, n))) - res = __copy_tofrom_user(to, from, n); - if (unlikely(res)) - memset(to + (n - res), 0, res); - return res; + return __copy_tofrom_user(to, (__force const void *)from, size); } - static inline unsigned long -copy_to_user(void *to, const void *from, unsigned long n) +raw_copy_to_user(void *to, const void __user *from, unsigned long size) { - if (likely(access_ok(VERIFY_WRITE, to, n))) - n = __copy_tofrom_user(to, from, n); - return n; + return __copy_tofrom_user((__force void *)to, from, size); } +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER extern unsigned long __clear_user(void *addr, unsigned long size); @@ -297,7 +260,7 @@ clear_user(void *addr, unsigned long size) } #define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) + (uaccess_kernel() ? ~0UL : TASK_SIZE) extern long strncpy_from_user(char *dest, const char __user *src, long count); diff --git a/arch/openrisc/kernel/or32_ksyms.c b/arch/openrisc/kernel/or32_ksyms.c index 5c4695d13542..ee3e604959e1 100644 --- a/arch/openrisc/kernel/or32_ksyms.c +++ b/arch/openrisc/kernel/or32_ksyms.c @@ -30,6 +30,7 @@ #include <asm/hardirq.h> #include <asm/delay.h> #include <asm/pgalloc.h> +#include <asm/pgtable.h> #define DECLARE_EXPORT(name) extern void name(void); EXPORT_SYMBOL(name) @@ -42,6 +43,9 @@ DECLARE_EXPORT(__muldi3); DECLARE_EXPORT(__ashrdi3); DECLARE_EXPORT(__ashldi3); DECLARE_EXPORT(__lshrdi3); +DECLARE_EXPORT(__ucmpdi2); +EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(__copy_tofrom_user); +EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(memset); diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 828a29110459..f8da545854f9 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -90,6 +90,7 @@ void arch_cpu_idle(void) } void (*pm_power_off) (void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); /* * When a process does an "exec", machine state like FPU and debug diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index ad294b3fb90b..531da9eb8f43 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -26,7 +26,6 @@ config PARISC select SYSCTL_ARCH_UNALIGN_ALLOW select SYSCTL_EXCEPTION_TRACE select HAVE_MOD_ARCH_SPECIFIC - select HAVE_ARCH_HARDENED_USERCOPY select VIRT_TO_BUS select MODULES_USE_ELF_RELA select CLONE_BACKWARDS diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h index 62a33338549c..d2742273a685 100644 --- a/arch/parisc/include/asm/bug.h +++ b/arch/parisc/include/asm/bug.h @@ -46,7 +46,7 @@ #endif #ifdef CONFIG_DEBUG_BUGVERBOSE -#define __WARN_TAINT(taint) \ +#define __WARN_FLAGS(flags) \ do { \ asm volatile("\n" \ "1:\t" PARISC_BUG_BREAK_ASM "\n" \ @@ -56,11 +56,11 @@ "\t.org 2b+%c3\n" \ "\t.popsection" \ : : "i" (__FILE__), "i" (__LINE__), \ - "i" (BUGFLAG_TAINT(taint)), \ + "i" (BUGFLAG_WARNING|(flags)), \ "i" (sizeof(struct bug_entry)) ); \ } while(0) #else -#define __WARN_TAINT(taint) \ +#define __WARN_FLAGS(flags) \ do { \ asm volatile("\n" \ "1:\t" PARISC_BUG_BREAK_ASM "\n" \ @@ -69,7 +69,7 @@ "\t.short %c0\n" \ "\t.org 2b+%c1\n" \ "\t.popsection" \ - : : "i" (BUGFLAG_TAINT(taint)), \ + : : "i" (BUGFLAG_WARNING|(flags)), \ "i" (sizeof(struct bug_entry)) ); \ } while(0) #endif diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index 19c9c3c5f267..c7e15cc5c668 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -43,28 +43,9 @@ static inline void flush_kernel_dcache_page(struct page *page) #define flush_kernel_dcache_range(start,size) \ flush_kernel_dcache_range_asm((start), (start)+(size)); -/* vmap range flushes and invalidates. Architecturally, we don't need - * the invalidate, because the CPU should refuse to speculate once an - * area has been flushed, so invalidate is left empty */ -static inline void flush_kernel_vmap_range(void *vaddr, int size) -{ - unsigned long start = (unsigned long)vaddr; - - flush_kernel_dcache_range_asm(start, start + size); -} -static inline void invalidate_kernel_vmap_range(void *vaddr, int size) -{ - unsigned long start = (unsigned long)vaddr; - void *cursor = vaddr; - for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) { - struct page *page = vmalloc_to_page(cursor); - - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) - flush_kernel_dcache_page(page); - } - flush_kernel_dcache_range_asm(start, start + size); -} +void flush_kernel_vmap_range(void *vaddr, int size); +void invalidate_kernel_vmap_range(void *vaddr, int size); #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h index ac8bd586ace8..0ba14300cd8e 100644 --- a/arch/parisc/include/asm/futex.h +++ b/arch/parisc/include/asm/futex.h @@ -109,7 +109,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is * our gateway page, and causes no end of trouble... */ - if (segment_eq(KERNEL_DS, get_fs()) && !uaddr) + if (uaccess_kernel() && !uaddr) return -EFAULT; if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index fb4382c28259..6b113f39f30c 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -6,15 +6,10 @@ */ #include <asm/page.h> #include <asm/cache.h> -#include <asm/errno.h> #include <asm-generic/uaccess-unaligned.h> #include <linux/bug.h> #include <linux/string.h> -#include <linux/thread_info.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 #define KERNEL_DS ((mm_segment_t){0}) #define USER_DS ((mm_segment_t){1}) @@ -32,16 +27,17 @@ * that put_user is the same as __put_user, etc. */ -#define access_ok(type, uaddr, size) (1) +#define access_ok(type, uaddr, size) \ + ( (uaddr) == (uaddr) ) #define put_user __put_user #define get_user __get_user #if !defined(CONFIG_64BIT) -#define LDD_USER(ptr) __get_user_asm64(ptr) +#define LDD_USER(val, ptr) __get_user_asm64(val, ptr) #define STD_USER(x, ptr) __put_user_asm64(x, ptr) #else -#define LDD_USER(ptr) __get_user_asm("ldd", ptr) +#define LDD_USER(val, ptr) __get_user_asm(val, "ldd", ptr) #define STD_USER(x, ptr) __put_user_asm("std", x, ptr) #endif @@ -64,6 +60,15 @@ struct exception_table_entry { ".previous\n" /* + * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry + * (with lowest bit set) for which the fault handler in fixup_exception() will + * load -EFAULT into %r8 for a read or write fault, and zeroes the target + * register in case of a read fault in get_user(). + */ +#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\ + ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1) + +/* * The page fault handler stores, in a per-cpu area, the following information * if a fixup routine is available. */ @@ -87,92 +92,116 @@ struct exception_data { " mtsp %0,%%sr2\n\t" \ : : "r"(get_fs()) : ) -#define __get_user(x, ptr) \ -({ \ - register long __gu_err __asm__ ("r8") = 0; \ - register long __gu_val __asm__ ("r9") = 0; \ - \ - load_sr2(); \ - switch (sizeof(*(ptr))) { \ - case 1: __get_user_asm("ldb", ptr); break; \ - case 2: __get_user_asm("ldh", ptr); break; \ - case 4: __get_user_asm("ldw", ptr); break; \ - case 8: LDD_USER(ptr); break; \ - default: BUILD_BUG(); break; \ - } \ - \ - (x) = (__force __typeof__(*(ptr))) __gu_val; \ - __gu_err; \ +#define __get_user_internal(val, ptr) \ +({ \ + register long __gu_err __asm__ ("r8") = 0; \ + \ + switch (sizeof(*(ptr))) { \ + case 1: __get_user_asm(val, "ldb", ptr); break; \ + case 2: __get_user_asm(val, "ldh", ptr); break; \ + case 4: __get_user_asm(val, "ldw", ptr); break; \ + case 8: LDD_USER(val, ptr); break; \ + default: BUILD_BUG(); \ + } \ + \ + __gu_err; \ +}) + +#define __get_user(val, ptr) \ +({ \ + load_sr2(); \ + __get_user_internal(val, ptr); \ }) -#define __get_user_asm(ldx, ptr) \ - __asm__("\n1:\t" ldx "\t0(%%sr2,%2),%0\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\ +#define __get_user_asm(val, ldx, ptr) \ +{ \ + register long __gu_val; \ + \ + __asm__("1: " ldx " 0(%%sr2,%2),%0\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ : "=r"(__gu_val), "=r"(__gu_err) \ - : "r"(ptr), "1"(__gu_err) \ - : "r1"); + : "r"(ptr), "1"(__gu_err)); \ + \ + (val) = (__force __typeof__(*(ptr))) __gu_val; \ +} #if !defined(CONFIG_64BIT) -#define __get_user_asm64(ptr) \ - __asm__("\n1:\tldw 0(%%sr2,%2),%0" \ - "\n2:\tldw 4(%%sr2,%2),%R0\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_2)\ - ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_get_user_skip_1)\ - : "=r"(__gu_val), "=r"(__gu_err) \ - : "r"(ptr), "1"(__gu_err) \ - : "r1"); +#define __get_user_asm64(val, ptr) \ +{ \ + union { \ + unsigned long long l; \ + __typeof__(*(ptr)) t; \ + } __gu_tmp; \ + \ + __asm__(" copy %%r0,%R0\n" \ + "1: ldw 0(%%sr2,%2),%0\n" \ + "2: ldw 4(%%sr2,%2),%R0\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \ + : "=&r"(__gu_tmp.l), "=r"(__gu_err) \ + : "r"(ptr), "1"(__gu_err)); \ + \ + (val) = __gu_tmp.t; \ +} #endif /* !defined(CONFIG_64BIT) */ -#define __put_user(x, ptr) \ +#define __put_user_internal(x, ptr) \ ({ \ register long __pu_err __asm__ ("r8") = 0; \ __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ \ - load_sr2(); \ switch (sizeof(*(ptr))) { \ - case 1: __put_user_asm("stb", __x, ptr); break; \ - case 2: __put_user_asm("sth", __x, ptr); break; \ - case 4: __put_user_asm("stw", __x, ptr); break; \ - case 8: STD_USER(__x, ptr); break; \ - default: BUILD_BUG(); break; \ - } \ + case 1: __put_user_asm("stb", __x, ptr); break; \ + case 2: __put_user_asm("sth", __x, ptr); break; \ + case 4: __put_user_asm("stw", __x, ptr); break; \ + case 8: STD_USER(__x, ptr); break; \ + default: BUILD_BUG(); \ + } \ \ __pu_err; \ }) +#define __put_user(x, ptr) \ +({ \ + load_sr2(); \ + __put_user_internal(x, ptr); \ +}) + + /* * The "__put_user/kernel_asm()" macros tell gcc they read from memory * instead of writing. This is because they do not write to any memory * gcc knows about, so there are no aliasing issues. These macros must - * also be aware that "fixup_put_user_skip_[12]" are executed in the - * context of the fault, and any registers used there must be listed - * as clobbers. In this case only "r1" is used by the current routines. - * r8/r9 are already listed as err/val. + * also be aware that fixups are executed in the context of the fault, + * and any registers used there must be listed as clobbers. + * r8 is already listed as err. */ #define __put_user_asm(stx, x, ptr) \ __asm__ __volatile__ ( \ - "\n1:\t" stx "\t%2,0(%%sr2,%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\ + "1: " stx " %2,0(%%sr2,%1)\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ : "=r"(__pu_err) \ - : "r"(ptr), "r"(x), "0"(__pu_err) \ - : "r1") + : "r"(ptr), "r"(x), "0"(__pu_err)) #if !defined(CONFIG_64BIT) #define __put_user_asm64(__val, ptr) do { \ __asm__ __volatile__ ( \ - "\n1:\tstw %2,0(%%sr2,%1)" \ - "\n2:\tstw %R2,4(%%sr2,%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\ - ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\ + "1: stw %2,0(%%sr2,%1)\n" \ + "2: stw %R2,4(%%sr2,%1)\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \ : "=r"(__pu_err) \ - : "r"(ptr), "r"(__val), "0"(__pu_err) \ - : "r1"); \ + : "r"(ptr), "r"(__val), "0"(__pu_err)); \ } while (0) #endif /* !defined(CONFIG_64BIT) */ @@ -182,9 +211,6 @@ struct exception_data { * Complex access routines -- external declarations */ -extern unsigned long lcopy_to_user(void __user *, const void *, unsigned long); -extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long); -extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long); extern long strncpy_from_user(char *, const char __user *, long); extern unsigned lclear_user(void __user *, unsigned long); extern long lstrnlen_user(const char __user *, long); @@ -198,59 +224,14 @@ extern long lstrnlen_user(const char __user *, long); #define clear_user lclear_user #define __clear_user lclear_user -unsigned long __must_check __copy_to_user(void __user *dst, const void *src, - unsigned long len); -unsigned long __must_check __copy_from_user(void *dst, const void __user *src, - unsigned long len); -unsigned long copy_in_user(void __user *dst, const void __user *src, - unsigned long len); -#define __copy_in_user copy_in_user -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -extern void __compiletime_error("usercopy buffer size is too small") -__bad_copy_user(void); - -static inline void copy_user_overflow(int size, unsigned long count) -{ - WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); -} - -static __always_inline unsigned long __must_check -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - int sz = __compiletime_object_size(to); - unsigned long ret = n; - - if (likely(sz < 0 || sz >= n)) { - check_object_size(to, n, false); - ret = __copy_from_user(to, from, n); - } else if (!__builtin_constant_p(n)) - copy_user_overflow(sz, n); - else - __bad_copy_user(); - - if (unlikely(ret)) - memset(to + (n - ret), 0, ret); - - return ret; -} - -static __always_inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - int sz = __compiletime_object_size(from); - - if (likely(sz < 0 || sz >= n)) { - check_object_size(from, n, true); - n = __copy_to_user(to, from, n); - } else if (!__builtin_constant_p(n)) - copy_user_overflow(sz, n); - else - __bad_copy_user(); - - return n; -} +unsigned long __must_check raw_copy_to_user(void __user *dst, const void *src, + unsigned long len); +unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src, + unsigned long len); +unsigned long __must_check raw_copy_in_user(void __user *dst, const void __user *src, + unsigned long len); +#define INLINE_COPY_TO_USER +#define INLINE_COPY_FROM_USER struct pt_regs; int fixup_exception(struct pt_regs *regs); diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 7a109b73ddf7..514701840bd9 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -91,4 +91,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 0x402F +#define SO_MEMINFO 0x4030 + +#define SO_INCOMING_NAPI_ID 0x4031 + +#define SO_COOKIE 0x4032 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index 6b0741e7a7ed..667c99421003 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h @@ -362,8 +362,9 @@ #define __NR_copy_file_range (__NR_Linux + 346) #define __NR_preadv2 (__NR_Linux + 347) #define __NR_pwritev2 (__NR_Linux + 348) +#define __NR_statx (__NR_Linux + 349) -#define __NR_Linux_syscalls (__NR_pwritev2 + 1) +#define __NR_Linux_syscalls (__NR_statx + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 0dc72d5de861..c32a09095216 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -616,3 +616,25 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn)); } } + +void flush_kernel_vmap_range(void *vaddr, int size) +{ + unsigned long start = (unsigned long)vaddr; + + if ((unsigned long)size > parisc_cache_flush_threshold) + flush_data_cache(); + else + flush_kernel_dcache_range_asm(start, start + size); +} +EXPORT_SYMBOL(flush_kernel_vmap_range); + +void invalidate_kernel_vmap_range(void *vaddr, int size) +{ + unsigned long start = (unsigned long)vaddr; + + if ((unsigned long)size > parisc_cache_flush_threshold) + flush_data_cache(); + else + flush_kernel_dcache_range_asm(start, start + size); +} +EXPORT_SYMBOL(invalidate_kernel_vmap_range); diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index a0ecdb4abcc8..c66c943d9322 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -620,6 +620,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, */ *loc = fsel(val, addend); break; + case R_PARISC_SECREL32: + /* 32-bit section relative address. */ + *loc = fsel(val, addend); + break; case R_PARISC_DPREL21L: /* left 21 bit of relative address */ val = lrsel(val - dp, addend); @@ -807,6 +811,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, */ *loc = fsel(val, addend); break; + case R_PARISC_SECREL32: + /* 32-bit section relative address. */ + *loc = fsel(val, addend); + break; case R_PARISC_FPTR64: /* 64-bit function address */ if(in_local(me, (void *)(val + addend))) { diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 7484b3d11e0d..c6d6272a934f 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -47,16 +47,6 @@ EXPORT_SYMBOL(__cmpxchg_u64); EXPORT_SYMBOL(lclear_user); EXPORT_SYMBOL(lstrnlen_user); -/* Global fixups - defined as int to avoid creation of function pointers */ -extern int fixup_get_user_skip_1; -extern int fixup_get_user_skip_2; -extern int fixup_put_user_skip_1; -extern int fixup_put_user_skip_2; -EXPORT_SYMBOL(fixup_get_user_skip_1); -EXPORT_SYMBOL(fixup_get_user_skip_2); -EXPORT_SYMBOL(fixup_put_user_skip_1); -EXPORT_SYMBOL(fixup_put_user_skip_2); - #ifndef CONFIG_64BIT /* Needed so insmod can set dp value */ extern int $global$; diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index e282a5131d77..6017a5af2e6e 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -39,7 +39,7 @@ * the PDC INTRIGUE calls. This is done to eliminate bugs introduced * in various PDC revisions. The code is much more maintainable * and reliable this way vs having to debug on every version of PDC - * on every box. + * on every box. */ #include <linux/capability.h> @@ -195,8 +195,8 @@ static int perf_config(uint32_t *image_ptr); static int perf_release(struct inode *inode, struct file *file); static int perf_open(struct inode *inode, struct file *file); static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos); -static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, - loff_t *ppos); +static ssize_t perf_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos); static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static void perf_start_counters(void); static int perf_stop_counters(uint32_t *raddr); @@ -222,7 +222,7 @@ extern void perf_intrigue_disable_perf_counters (void); /* * configure: * - * Configure the cpu with a given data image. First turn off the counters, + * Configure the cpu with a given data image. First turn off the counters, * then download the image, then turn the counters back on. */ static int perf_config(uint32_t *image_ptr) @@ -234,7 +234,7 @@ static int perf_config(uint32_t *image_ptr) error = perf_stop_counters(raddr); if (error != 0) { printk("perf_config: perf_stop_counters = %ld\n", error); - return -EINVAL; + return -EINVAL; } printk("Preparing to write image\n"); @@ -242,7 +242,7 @@ printk("Preparing to write image\n"); error = perf_write_image((uint64_t *)image_ptr); if (error != 0) { printk("perf_config: DOWNLOAD = %ld\n", error); - return -EINVAL; + return -EINVAL; } printk("Preparing to start counters\n"); @@ -254,7 +254,7 @@ printk("Preparing to start counters\n"); } /* - * Open the device and initialize all of its memory. The device is only + * Open the device and initialize all of its memory. The device is only * opened once, but can be "queried" by multiple processes that know its * file descriptor. */ @@ -298,19 +298,19 @@ static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t * called on the processor that the download should happen * on. */ -static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, - loff_t *ppos) +static ssize_t perf_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { size_t image_size; uint32_t image_type; uint32_t interface_type; uint32_t test; - if (perf_processor_interface == ONYX_INTF) + if (perf_processor_interface == ONYX_INTF) image_size = PCXU_IMAGE_SIZE; - else if (perf_processor_interface == CUDA_INTF) + else if (perf_processor_interface == CUDA_INTF) image_size = PCXW_IMAGE_SIZE; - else + else return -EFAULT; if (!capable(CAP_SYS_ADMIN)) @@ -330,22 +330,22 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun /* First check the machine type is correct for the requested image */ - if (((perf_processor_interface == CUDA_INTF) && - (interface_type != CUDA_INTF)) || - ((perf_processor_interface == ONYX_INTF) && - (interface_type != ONYX_INTF))) + if (((perf_processor_interface == CUDA_INTF) && + (interface_type != CUDA_INTF)) || + ((perf_processor_interface == ONYX_INTF) && + (interface_type != ONYX_INTF))) return -EINVAL; /* Next check to make sure the requested image is valid */ - if (((interface_type == CUDA_INTF) && + if (((interface_type == CUDA_INTF) && (test >= MAX_CUDA_IMAGES)) || - ((interface_type == ONYX_INTF) && - (test >= MAX_ONYX_IMAGES))) + ((interface_type == ONYX_INTF) && + (test >= MAX_ONYX_IMAGES))) return -EINVAL; /* Copy the image into the processor */ - if (interface_type == CUDA_INTF) + if (interface_type == CUDA_INTF) return perf_config(cuda_images[test]); else return perf_config(onyx_images[test]); @@ -359,7 +359,7 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun static void perf_patch_images(void) { #if 0 /* FIXME!! */ -/* +/* * NOTE: this routine is VERY specific to the current TLB image. * If the image is changed, this routine might also need to be changed. */ @@ -367,9 +367,9 @@ static void perf_patch_images(void) extern void $i_dtlb_miss_2_0(); extern void PA2_0_iva(); - /* + /* * We can only use the lower 32-bits, the upper 32-bits should be 0 - * anyway given this is in the kernel + * anyway given this is in the kernel */ uint32_t itlb_addr = (uint32_t)&($i_itlb_miss_2_0); uint32_t dtlb_addr = (uint32_t)&($i_dtlb_miss_2_0); @@ -377,21 +377,21 @@ static void perf_patch_images(void) if (perf_processor_interface == ONYX_INTF) { /* clear last 2 bytes */ - onyx_images[TLBMISS][15] &= 0xffffff00; + onyx_images[TLBMISS][15] &= 0xffffff00; /* set 2 bytes */ onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00; onyx_images[TLBMISS][17] = itlb_addr; /* clear last 2 bytes */ - onyx_images[TLBHANDMISS][15] &= 0xffffff00; + onyx_images[TLBHANDMISS][15] &= 0xffffff00; /* set 2 bytes */ onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00; onyx_images[TLBHANDMISS][17] = itlb_addr; /* clear last 2 bytes */ - onyx_images[BIG_CPI][15] &= 0xffffff00; + onyx_images[BIG_CPI][15] &= 0xffffff00; /* set 2 bytes */ onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24)); onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00; @@ -404,24 +404,24 @@ static void perf_patch_images(void) } else if (perf_processor_interface == CUDA_INTF) { /* Cuda interface */ - cuda_images[TLBMISS][16] = + cuda_images[TLBMISS][16] = (cuda_images[TLBMISS][16]&0xffff0000) | ((dtlb_addr >> 8)&0x0000ffff); - cuda_images[TLBMISS][17] = + cuda_images[TLBMISS][17] = ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000; - cuda_images[TLBHANDMISS][16] = + cuda_images[TLBHANDMISS][16] = (cuda_images[TLBHANDMISS][16]&0xffff0000) | ((dtlb_addr >> 8)&0x0000ffff); - cuda_images[TLBHANDMISS][17] = + cuda_images[TLBHANDMISS][17] = ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000; - cuda_images[BIG_CPI][16] = + cuda_images[BIG_CPI][16] = (cuda_images[BIG_CPI][16]&0xffff0000) | ((dtlb_addr >> 8)&0x0000ffff); - cuda_images[BIG_CPI][17] = + cuda_images[BIG_CPI][17] = ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000; } else { @@ -433,7 +433,7 @@ static void perf_patch_images(void) /* * ioctl routine - * All routines effect the processor that they are executed on. Thus you + * All routines effect the processor that they are executed on. Thus you * must be running on the processor that you wish to change. */ @@ -459,7 +459,7 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } /* copy out the Counters */ - if (copy_to_user((void __user *)arg, raddr, + if (copy_to_user((void __user *)arg, raddr, sizeof (raddr)) != 0) { error = -EFAULT; break; @@ -487,7 +487,7 @@ static const struct file_operations perf_fops = { .open = perf_open, .release = perf_release }; - + static struct miscdevice perf_dev = { MISC_DYNAMIC_MINOR, PA_PERF_DEV, @@ -595,7 +595,7 @@ static int perf_stop_counters(uint32_t *raddr) /* OR sticky2 (bit 1496) to counter2 bit 32 */ tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000; raddr[2] = (uint32_t)tmp64; - + /* Counter3 is bits 1497 to 1528 */ tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff; /* OR sticky3 (bit 1529) to counter3 bit 32 */ @@ -617,7 +617,7 @@ static int perf_stop_counters(uint32_t *raddr) userbuf[22] = 0; userbuf[23] = 0; - /* + /* * Write back the zeroed bytes + the image given * the read was destructive. */ @@ -625,13 +625,13 @@ static int perf_stop_counters(uint32_t *raddr) } else { /* - * Read RDR-15 which contains the counters and sticky bits + * Read RDR-15 which contains the counters and sticky bits */ if (!perf_rdr_read_ubuf(15, userbuf)) { return -13; } - /* + /* * Clear out the counters */ perf_rdr_clear(15); @@ -644,7 +644,7 @@ static int perf_stop_counters(uint32_t *raddr) raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL); raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL); } - + return 0; } @@ -682,7 +682,7 @@ static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer) i = tentry->num_words; while (i--) { buffer[i] = 0; - } + } /* Check for bits an even number of 64 */ if ((xbits = width & 0x03f) != 0) { @@ -808,18 +808,22 @@ static int perf_write_image(uint64_t *memaddr) } runway = ioremap_nocache(cpu_device->hpa.start, 4096); + if (!runway) { + pr_err("perf_write_image: ioremap failed!\n"); + return -ENOMEM; + } /* Merge intrigue bits into Runway STATUS 0 */ tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful; - __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), + __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), runway + RUNWAY_STATUS); - + /* Write RUNWAY DEBUG registers */ for (i = 0; i < 8; i++) { __raw_writeq(*memaddr++, runway + RUNWAY_DEBUG); } - return 0; + return 0; } /* @@ -843,7 +847,7 @@ printk("perf_rdr_write\n"); perf_rdr_shift_out_U(rdr_num, buffer[i]); } else { perf_rdr_shift_out_W(rdr_num, buffer[i]); - } + } } printk("perf_rdr_write done\n"); } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 06f7ca7fe70b..4516a5b53f38 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -142,6 +142,10 @@ void machine_power_off(void) printk(KERN_EMERG "System shut down completed.\n" "Please power this system off now."); + + /* prevent soft lockup/stalled CPU messages for endless loop. */ + rcu_sysrq_start(); + for (;;); } void (*pm_power_off)(void) = machine_power_off; diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 3cfef1de8061..44aeaa9c039f 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -444,6 +444,7 @@ ENTRY_SAME(copy_file_range) ENTRY_COMP(preadv2) ENTRY_COMP(pwritev2) + ENTRY_SAME(statx) .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b)) diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile index 8fa92b8d839a..f2dac4d73b1b 100644 --- a/arch/parisc/lib/Makefile +++ b/arch/parisc/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for parisc-specific library files # -lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o \ +lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \ ucmpdi2.o delay.o obj-y := iomap.o diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S deleted file mode 100644 index a5b72f22c7a6..000000000000 --- a/arch/parisc/lib/fixup.S +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Linux/PA-RISC Project (http://www.parisc-linux.org/) - * - * Copyright (C) 2004 Randolph Chung <tausq@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Fixup routines for kernel exception handling. - */ -#include <asm/asm-offsets.h> -#include <asm/assembly.h> -#include <asm/errno.h> -#include <linux/linkage.h> - -#ifdef CONFIG_SMP - .macro get_fault_ip t1 t2 - loadgp - addil LT%__per_cpu_offset,%r27 - LDREG RT%__per_cpu_offset(%r1),\t1 - /* t2 = smp_processor_id() */ - mfctl 30,\t2 - ldw TI_CPU(\t2),\t2 -#ifdef CONFIG_64BIT - extrd,u \t2,63,32,\t2 -#endif - /* t2 = &__per_cpu_offset[smp_processor_id()]; */ - LDREGX \t2(\t1),\t2 - addil LT%exception_data,%r27 - LDREG RT%exception_data(%r1),\t1 - /* t1 = this_cpu_ptr(&exception_data) */ - add,l \t1,\t2,\t1 - /* %r27 = t1->fault_gp - restore gp */ - LDREG EXCDATA_GP(\t1), %r27 - /* t1 = t1->fault_ip */ - LDREG EXCDATA_IP(\t1), \t1 - .endm -#else - .macro get_fault_ip t1 t2 - loadgp - /* t1 = this_cpu_ptr(&exception_data) */ - addil LT%exception_data,%r27 - LDREG RT%exception_data(%r1),\t2 - /* %r27 = t2->fault_gp - restore gp */ - LDREG EXCDATA_GP(\t2), %r27 - /* t1 = t2->fault_ip */ - LDREG EXCDATA_IP(\t2), \t1 - .endm -#endif - - .level LEVEL - - .text - .section .fixup, "ax" - - /* get_user() fixups, store -EFAULT in r8, and 0 in r9 */ -ENTRY_CFI(fixup_get_user_skip_1) - get_fault_ip %r1,%r8 - ldo 4(%r1), %r1 - ldi -EFAULT, %r8 - bv %r0(%r1) - copy %r0, %r9 -ENDPROC_CFI(fixup_get_user_skip_1) - -ENTRY_CFI(fixup_get_user_skip_2) - get_fault_ip %r1,%r8 - ldo 8(%r1), %r1 - ldi -EFAULT, %r8 - bv %r0(%r1) - copy %r0, %r9 -ENDPROC_CFI(fixup_get_user_skip_2) - - /* put_user() fixups, store -EFAULT in r8 */ -ENTRY_CFI(fixup_put_user_skip_1) - get_fault_ip %r1,%r8 - ldo 4(%r1), %r1 - bv %r0(%r1) - ldi -EFAULT, %r8 -ENDPROC_CFI(fixup_put_user_skip_1) - -ENTRY_CFI(fixup_put_user_skip_2) - get_fault_ip %r1,%r8 - ldo 8(%r1), %r1 - bv %r0(%r1) - ldi -EFAULT, %r8 -ENDPROC_CFI(fixup_put_user_skip_2) - diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S index 56845de6b5df..85c28bb80fb7 100644 --- a/arch/parisc/lib/lusercopy.S +++ b/arch/parisc/lib/lusercopy.S @@ -5,6 +5,8 @@ * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org> * Copyright (C) 2001 Matthieu Delahaye <delahaym at esiee.fr> * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org> + * Copyright (C) 2017 Helge Deller <deller@gmx.de> + * Copyright (C) 2017 John David Anglin <dave.anglin@bell.net> * * * This program is free software; you can redistribute it and/or modify @@ -132,4 +134,321 @@ ENDPROC_CFI(lstrnlen_user) .procend + + +/* + * unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) + * + * Inputs: + * - sr1 already contains space of source region + * - sr2 already contains space of destination region + * + * Returns: + * - number of bytes that could not be copied. + * On success, this will be zero. + * + * This code is based on a C-implementation of a copy routine written by + * Randolph Chung, which in turn was derived from the glibc. + * + * Several strategies are tried to try to get the best performance for various + * conditions. In the optimal case, we copy by loops that copy 32- or 16-bytes + * at a time using general registers. Unaligned copies are handled either by + * aligning the destination and then using shift-and-write method, or in a few + * cases by falling back to a byte-at-a-time copy. + * + * Testing with various alignments and buffer sizes shows that this code is + * often >10x faster than a simple byte-at-a-time copy, even for strangely + * aligned operands. It is interesting to note that the glibc version of memcpy + * (written in C) is actually quite fast already. This routine is able to beat + * it by 30-40% for aligned copies because of the loop unrolling, but in some + * cases the glibc version is still slightly faster. This lends more + * credibility that gcc can generate very good code as long as we are careful. + * + * Possible optimizations: + * - add cache prefetching + * - try not to use the post-increment address modifiers; they may create + * additional interlocks. Assumption is that those were only efficient on old + * machines (pre PA8000 processors) + */ + + dst = arg0 + src = arg1 + len = arg2 + end = arg3 + t1 = r19 + t2 = r20 + t3 = r21 + t4 = r22 + srcspc = sr1 + dstspc = sr2 + + t0 = r1 + a1 = t1 + a2 = t2 + a3 = t3 + a0 = t4 + + save_src = ret0 + save_dst = ret1 + save_len = r31 + +ENTRY_CFI(pa_memcpy) + .proc + .callinfo NO_CALLS + .entry + + /* Last destination address */ + add dst,len,end + + /* short copy with less than 16 bytes? */ + cmpib,COND(>>=),n 15,len,.Lbyte_loop + + /* same alignment? */ + xor src,dst,t0 + extru t0,31,2,t1 + cmpib,<>,n 0,t1,.Lunaligned_copy + +#ifdef CONFIG_64BIT + /* only do 64-bit copies if we can get aligned. */ + extru t0,31,3,t1 + cmpib,<>,n 0,t1,.Lalign_loop32 + + /* loop until we are 64-bit aligned */ +.Lalign_loop64: + extru dst,31,3,t1 + cmpib,=,n 0,t1,.Lcopy_loop_16_start +20: ldb,ma 1(srcspc,src),t1 +21: stb,ma t1,1(dstspc,dst) + b .Lalign_loop64 + ldo -1(len),len + + ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + +.Lcopy_loop_16_start: + ldi 31,t0 +.Lcopy_loop_16: + cmpb,COND(>>=),n t0,len,.Lword_loop + +10: ldd 0(srcspc,src),t1 +11: ldd 8(srcspc,src),t2 + ldo 16(src),src +12: std,ma t1,8(dstspc,dst) +13: std,ma t2,8(dstspc,dst) +14: ldd 0(srcspc,src),t1 +15: ldd 8(srcspc,src),t2 + ldo 16(src),src +16: std,ma t1,8(dstspc,dst) +17: std,ma t2,8(dstspc,dst) + + ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(11b,.Lcopy16_fault) + ASM_EXCEPTIONTABLE_ENTRY(12b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(13b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(14b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(15b,.Lcopy16_fault) + ASM_EXCEPTIONTABLE_ENTRY(16b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(17b,.Lcopy_done) + + b .Lcopy_loop_16 + ldo -32(len),len + +.Lword_loop: + cmpib,COND(>>=),n 3,len,.Lbyte_loop +20: ldw,ma 4(srcspc,src),t1 +21: stw,ma t1,4(dstspc,dst) + b .Lword_loop + ldo -4(len),len + + ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + +#endif /* CONFIG_64BIT */ + + /* loop until we are 32-bit aligned */ +.Lalign_loop32: + extru dst,31,2,t1 + cmpib,=,n 0,t1,.Lcopy_loop_8 +20: ldb,ma 1(srcspc,src),t1 +21: stb,ma t1,1(dstspc,dst) + b .Lalign_loop32 + ldo -1(len),len + + ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + + +.Lcopy_loop_8: + cmpib,COND(>>=),n 15,len,.Lbyte_loop + +10: ldw 0(srcspc,src),t1 +11: ldw 4(srcspc,src),t2 +12: stw,ma t1,4(dstspc,dst) +13: stw,ma t2,4(dstspc,dst) +14: ldw 8(srcspc,src),t1 +15: ldw 12(srcspc,src),t2 + ldo 16(src),src +16: stw,ma t1,4(dstspc,dst) +17: stw,ma t2,4(dstspc,dst) + + ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(11b,.Lcopy8_fault) + ASM_EXCEPTIONTABLE_ENTRY(12b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(13b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(14b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(15b,.Lcopy8_fault) + ASM_EXCEPTIONTABLE_ENTRY(16b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(17b,.Lcopy_done) + + b .Lcopy_loop_8 + ldo -16(len),len + +.Lbyte_loop: + cmpclr,COND(<>) len,%r0,%r0 + b,n .Lcopy_done +20: ldb 0(srcspc,src),t1 + ldo 1(src),src +21: stb,ma t1,1(dstspc,dst) + b .Lbyte_loop + ldo -1(len),len + + ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + +.Lcopy_done: + bv %r0(%r2) + sub end,dst,ret0 + + + /* src and dst are not aligned the same way. */ + /* need to go the hard way */ +.Lunaligned_copy: + /* align until dst is 32bit-word-aligned */ + extru dst,31,2,t1 + cmpib,=,n 0,t1,.Lcopy_dstaligned +20: ldb 0(srcspc,src),t1 + ldo 1(src),src +21: stb,ma t1,1(dstspc,dst) + b .Lunaligned_copy + ldo -1(len),len + + ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + +.Lcopy_dstaligned: + + /* store src, dst and len in safe place */ + copy src,save_src + copy dst,save_dst + copy len,save_len + + /* len now needs give number of words to copy */ + SHRREG len,2,len + + /* + * Copy from a not-aligned src to an aligned dst using shifts. + * Handles 4 words per loop. + */ + + depw,z src,28,2,t0 + subi 32,t0,t0 + mtsar t0 + extru len,31,2,t0 + cmpib,= 2,t0,.Lcase2 + /* Make src aligned by rounding it down. */ + depi 0,31,2,src + + cmpiclr,<> 3,t0,%r0 + b,n .Lcase3 + cmpiclr,<> 1,t0,%r0 + b,n .Lcase1 +.Lcase0: + cmpb,COND(=) %r0,len,.Lcda_finish + nop + +1: ldw,ma 4(srcspc,src), a3 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) +1: ldw,ma 4(srcspc,src), a0 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + b,n .Ldo3 +.Lcase1: +1: ldw,ma 4(srcspc,src), a2 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) +1: ldw,ma 4(srcspc,src), a3 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + ldo -1(len),len + cmpb,COND(=),n %r0,len,.Ldo0 +.Ldo4: +1: ldw,ma 4(srcspc,src), a0 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + shrpw a2, a3, %sar, t0 +1: stw,ma t0, 4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done) +.Ldo3: +1: ldw,ma 4(srcspc,src), a1 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + shrpw a3, a0, %sar, t0 +1: stw,ma t0, 4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done) +.Ldo2: +1: ldw,ma 4(srcspc,src), a2 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + shrpw a0, a1, %sar, t0 +1: stw,ma t0, 4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done) +.Ldo1: +1: ldw,ma 4(srcspc,src), a3 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + shrpw a1, a2, %sar, t0 +1: stw,ma t0, 4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done) + ldo -4(len),len + cmpb,COND(<>) %r0,len,.Ldo4 + nop +.Ldo0: + shrpw a2, a3, %sar, t0 +1: stw,ma t0, 4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done) + +.Lcda_rdfault: +.Lcda_finish: + /* calculate new src, dst and len and jump to byte-copy loop */ + sub dst,save_dst,t0 + add save_src,t0,src + b .Lbyte_loop + sub save_len,t0,len + +.Lcase3: +1: ldw,ma 4(srcspc,src), a0 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) +1: ldw,ma 4(srcspc,src), a1 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + b .Ldo2 + ldo 1(len),len +.Lcase2: +1: ldw,ma 4(srcspc,src), a1 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) +1: ldw,ma 4(srcspc,src), a2 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + b .Ldo1 + ldo 2(len),len + + + /* fault exception fixup handlers: */ +#ifdef CONFIG_64BIT +.Lcopy16_fault: + b .Lcopy_done +10: std,ma t1,8(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done) +#endif + +.Lcopy8_fault: + b .Lcopy_done +10: stw,ma t1,4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done) + + .exit +ENDPROC_CFI(pa_memcpy) + .procend + .end diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index f82ff10ed974..99115cd9e790 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -2,7 +2,7 @@ * Optimized memory copy routines. * * Copyright (C) 2004 Randolph Chung <tausq@debian.org> - * Copyright (C) 2013 Helge Deller <deller@gmx.de> + * Copyright (C) 2013-2017 Helge Deller <deller@gmx.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,493 +21,40 @@ * Portions derived from the GNU C Library * Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. * - * Several strategies are tried to try to get the best performance for various - * conditions. In the optimal case, we copy 64-bytes in an unrolled loop using - * fp regs. This is followed by loops that copy 32- or 16-bytes at a time using - * general registers. Unaligned copies are handled either by aligning the - * destination and then using shift-and-write method, or in a few cases by - * falling back to a byte-at-a-time copy. - * - * I chose to implement this in C because it is easier to maintain and debug, - * and in my experiments it appears that the C code generated by gcc (3.3/3.4 - * at the time of writing) is fairly optimal. Unfortunately some of the - * semantics of the copy routine (exception handling) is difficult to express - * in C, so we have to play some tricks to get it to work. - * - * All the loads and stores are done via explicit asm() code in order to use - * the right space registers. - * - * Testing with various alignments and buffer sizes shows that this code is - * often >10x faster than a simple byte-at-a-time copy, even for strangely - * aligned operands. It is interesting to note that the glibc version - * of memcpy (written in C) is actually quite fast already. This routine is - * able to beat it by 30-40% for aligned copies because of the loop unrolling, - * but in some cases the glibc version is still slightly faster. This lends - * more credibility that gcc can generate very good code as long as we are - * careful. - * - * TODO: - * - cache prefetching needs more experimentation to get optimal settings - * - try not to use the post-increment address modifiers; they create additional - * interlocks - * - replace byte-copy loops with stybs sequences */ -#ifdef __KERNEL__ #include <linux/module.h> #include <linux/compiler.h> #include <linux/uaccess.h> -#define s_space "%%sr1" -#define d_space "%%sr2" -#else -#include "memcpy.h" -#define s_space "%%sr0" -#define d_space "%%sr0" -#define pa_memcpy new2_copy -#endif DECLARE_PER_CPU(struct exception_data, exception_data); -#define preserve_branch(label) do { \ - volatile int dummy = 0; \ - /* The following branch is never taken, it's just here to */ \ - /* prevent gcc from optimizing away our exception code. */ \ - if (unlikely(dummy != dummy)) \ - goto label; \ -} while (0) - -#define get_user_space() (segment_eq(get_fs(), KERNEL_DS) ? 0 : mfsp(3)) +#define get_user_space() (uaccess_kernel() ? 0 : mfsp(3)) #define get_kernel_space() (0) -#define MERGE(w0, sh_1, w1, sh_2) ({ \ - unsigned int _r; \ - asm volatile ( \ - "mtsar %3\n" \ - "shrpw %1, %2, %%sar, %0\n" \ - : "=r"(_r) \ - : "r"(w0), "r"(w1), "r"(sh_2) \ - ); \ - _r; \ -}) -#define THRESHOLD 16 - -#ifdef DEBUG_MEMCPY -#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __func__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) -#else -#define DPRINTF(fmt, args...) -#endif - -#define def_load_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \ - __asm__ __volatile__ ( \ - "1:\t" #_insn ",ma " #_sz "(" _s ",%1), %0\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,_e) \ - : _tt(_t), "+r"(_a) \ - : \ - : "r8") - -#define def_store_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \ - __asm__ __volatile__ ( \ - "1:\t" #_insn ",ma %1, " #_sz "(" _s ",%0)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,_e) \ - : "+r"(_a) \ - : _tt(_t) \ - : "r8") - -#define ldbma(_s, _a, _t, _e) def_load_ai_insn(ldbs,1,"=r",_s,_a,_t,_e) -#define stbma(_s, _t, _a, _e) def_store_ai_insn(stbs,1,"r",_s,_a,_t,_e) -#define ldwma(_s, _a, _t, _e) def_load_ai_insn(ldw,4,"=r",_s,_a,_t,_e) -#define stwma(_s, _t, _a, _e) def_store_ai_insn(stw,4,"r",_s,_a,_t,_e) -#define flddma(_s, _a, _t, _e) def_load_ai_insn(fldd,8,"=f",_s,_a,_t,_e) -#define fstdma(_s, _t, _a, _e) def_store_ai_insn(fstd,8,"f",_s,_a,_t,_e) - -#define def_load_insn(_insn,_tt,_s,_o,_a,_t,_e) \ - __asm__ __volatile__ ( \ - "1:\t" #_insn " " #_o "(" _s ",%1), %0\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,_e) \ - : _tt(_t) \ - : "r"(_a) \ - : "r8") - -#define def_store_insn(_insn,_tt,_s,_t,_o,_a,_e) \ - __asm__ __volatile__ ( \ - "1:\t" #_insn " %0, " #_o "(" _s ",%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,_e) \ - : \ - : _tt(_t), "r"(_a) \ - : "r8") - -#define ldw(_s,_o,_a,_t,_e) def_load_insn(ldw,"=r",_s,_o,_a,_t,_e) -#define stw(_s,_t,_o,_a,_e) def_store_insn(stw,"r",_s,_t,_o,_a,_e) - -#ifdef CONFIG_PREFETCH -static inline void prefetch_src(const void *addr) -{ - __asm__("ldw 0(" s_space ",%0), %%r0" : : "r" (addr)); -} - -static inline void prefetch_dst(const void *addr) -{ - __asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr)); -} -#else -#define prefetch_src(addr) do { } while(0) -#define prefetch_dst(addr) do { } while(0) -#endif - -#define PA_MEMCPY_OK 0 -#define PA_MEMCPY_LOAD_ERROR 1 -#define PA_MEMCPY_STORE_ERROR 2 - -/* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words - * per loop. This code is derived from glibc. - */ -static noinline unsigned long copy_dstaligned(unsigned long dst, - unsigned long src, unsigned long len) -{ - /* gcc complains that a2 and a3 may be uninitialized, but actually - * they cannot be. Initialize a2/a3 to shut gcc up. - */ - register unsigned int a0, a1, a2 = 0, a3 = 0; - int sh_1, sh_2; - - /* prefetch_src((const void *)src); */ - - /* Calculate how to shift a word read at the memory operation - aligned srcp to make it aligned for copy. */ - sh_1 = 8 * (src % sizeof(unsigned int)); - sh_2 = 8 * sizeof(unsigned int) - sh_1; - - /* Make src aligned by rounding it down. */ - src &= -sizeof(unsigned int); - - switch (len % 4) - { - case 2: - /* a1 = ((unsigned int *) src)[0]; - a2 = ((unsigned int *) src)[1]; */ - ldw(s_space, 0, src, a1, cda_ldw_exc); - ldw(s_space, 4, src, a2, cda_ldw_exc); - src -= 1 * sizeof(unsigned int); - dst -= 3 * sizeof(unsigned int); - len += 2; - goto do1; - case 3: - /* a0 = ((unsigned int *) src)[0]; - a1 = ((unsigned int *) src)[1]; */ - ldw(s_space, 0, src, a0, cda_ldw_exc); - ldw(s_space, 4, src, a1, cda_ldw_exc); - src -= 0 * sizeof(unsigned int); - dst -= 2 * sizeof(unsigned int); - len += 1; - goto do2; - case 0: - if (len == 0) - return PA_MEMCPY_OK; - /* a3 = ((unsigned int *) src)[0]; - a0 = ((unsigned int *) src)[1]; */ - ldw(s_space, 0, src, a3, cda_ldw_exc); - ldw(s_space, 4, src, a0, cda_ldw_exc); - src -=-1 * sizeof(unsigned int); - dst -= 1 * sizeof(unsigned int); - len += 0; - goto do3; - case 1: - /* a2 = ((unsigned int *) src)[0]; - a3 = ((unsigned int *) src)[1]; */ - ldw(s_space, 0, src, a2, cda_ldw_exc); - ldw(s_space, 4, src, a3, cda_ldw_exc); - src -=-2 * sizeof(unsigned int); - dst -= 0 * sizeof(unsigned int); - len -= 1; - if (len == 0) - goto do0; - goto do4; /* No-op. */ - } - - do - { - /* prefetch_src((const void *)(src + 4 * sizeof(unsigned int))); */ -do4: - /* a0 = ((unsigned int *) src)[0]; */ - ldw(s_space, 0, src, a0, cda_ldw_exc); - /* ((unsigned int *) dst)[0] = MERGE (a2, sh_1, a3, sh_2); */ - stw(d_space, MERGE (a2, sh_1, a3, sh_2), 0, dst, cda_stw_exc); -do3: - /* a1 = ((unsigned int *) src)[1]; */ - ldw(s_space, 4, src, a1, cda_ldw_exc); - /* ((unsigned int *) dst)[1] = MERGE (a3, sh_1, a0, sh_2); */ - stw(d_space, MERGE (a3, sh_1, a0, sh_2), 4, dst, cda_stw_exc); -do2: - /* a2 = ((unsigned int *) src)[2]; */ - ldw(s_space, 8, src, a2, cda_ldw_exc); - /* ((unsigned int *) dst)[2] = MERGE (a0, sh_1, a1, sh_2); */ - stw(d_space, MERGE (a0, sh_1, a1, sh_2), 8, dst, cda_stw_exc); -do1: - /* a3 = ((unsigned int *) src)[3]; */ - ldw(s_space, 12, src, a3, cda_ldw_exc); - /* ((unsigned int *) dst)[3] = MERGE (a1, sh_1, a2, sh_2); */ - stw(d_space, MERGE (a1, sh_1, a2, sh_2), 12, dst, cda_stw_exc); - - src += 4 * sizeof(unsigned int); - dst += 4 * sizeof(unsigned int); - len -= 4; - } - while (len != 0); - -do0: - /* ((unsigned int *) dst)[0] = MERGE (a2, sh_1, a3, sh_2); */ - stw(d_space, MERGE (a2, sh_1, a3, sh_2), 0, dst, cda_stw_exc); - - preserve_branch(handle_load_error); - preserve_branch(handle_store_error); - - return PA_MEMCPY_OK; - -handle_load_error: - __asm__ __volatile__ ("cda_ldw_exc:\n"); - return PA_MEMCPY_LOAD_ERROR; - -handle_store_error: - __asm__ __volatile__ ("cda_stw_exc:\n"); - return PA_MEMCPY_STORE_ERROR; -} - - -/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR. - * In case of an access fault the faulty address can be read from the per_cpu - * exception data struct. */ -static noinline unsigned long pa_memcpy_internal(void *dstp, const void *srcp, - unsigned long len) -{ - register unsigned long src, dst, t1, t2, t3; - register unsigned char *pcs, *pcd; - register unsigned int *pws, *pwd; - register double *pds, *pdd; - unsigned long ret; - - src = (unsigned long)srcp; - dst = (unsigned long)dstp; - pcs = (unsigned char *)srcp; - pcd = (unsigned char *)dstp; - - /* prefetch_src((const void *)srcp); */ - - if (len < THRESHOLD) - goto byte_copy; - - /* Check alignment */ - t1 = (src ^ dst); - if (unlikely(t1 & (sizeof(double)-1))) - goto unaligned_copy; - - /* src and dst have same alignment. */ - - /* Copy bytes till we are double-aligned. */ - t2 = src & (sizeof(double) - 1); - if (unlikely(t2 != 0)) { - t2 = sizeof(double) - t2; - while (t2 && len) { - /* *pcd++ = *pcs++; */ - ldbma(s_space, pcs, t3, pmc_load_exc); - len--; - stbma(d_space, t3, pcd, pmc_store_exc); - t2--; - } - } - - pds = (double *)pcs; - pdd = (double *)pcd; - -#if 0 - /* Copy 8 doubles at a time */ - while (len >= 8*sizeof(double)) { - register double r1, r2, r3, r4, r5, r6, r7, r8; - /* prefetch_src((char *)pds + L1_CACHE_BYTES); */ - flddma(s_space, pds, r1, pmc_load_exc); - flddma(s_space, pds, r2, pmc_load_exc); - flddma(s_space, pds, r3, pmc_load_exc); - flddma(s_space, pds, r4, pmc_load_exc); - fstdma(d_space, r1, pdd, pmc_store_exc); - fstdma(d_space, r2, pdd, pmc_store_exc); - fstdma(d_space, r3, pdd, pmc_store_exc); - fstdma(d_space, r4, pdd, pmc_store_exc); - -#if 0 - if (L1_CACHE_BYTES <= 32) - prefetch_src((char *)pds + L1_CACHE_BYTES); -#endif - flddma(s_space, pds, r5, pmc_load_exc); - flddma(s_space, pds, r6, pmc_load_exc); - flddma(s_space, pds, r7, pmc_load_exc); - flddma(s_space, pds, r8, pmc_load_exc); - fstdma(d_space, r5, pdd, pmc_store_exc); - fstdma(d_space, r6, pdd, pmc_store_exc); - fstdma(d_space, r7, pdd, pmc_store_exc); - fstdma(d_space, r8, pdd, pmc_store_exc); - len -= 8*sizeof(double); - } -#endif - - pws = (unsigned int *)pds; - pwd = (unsigned int *)pdd; - -word_copy: - while (len >= 8*sizeof(unsigned int)) { - register unsigned int r1,r2,r3,r4,r5,r6,r7,r8; - /* prefetch_src((char *)pws + L1_CACHE_BYTES); */ - ldwma(s_space, pws, r1, pmc_load_exc); - ldwma(s_space, pws, r2, pmc_load_exc); - ldwma(s_space, pws, r3, pmc_load_exc); - ldwma(s_space, pws, r4, pmc_load_exc); - stwma(d_space, r1, pwd, pmc_store_exc); - stwma(d_space, r2, pwd, pmc_store_exc); - stwma(d_space, r3, pwd, pmc_store_exc); - stwma(d_space, r4, pwd, pmc_store_exc); - - ldwma(s_space, pws, r5, pmc_load_exc); - ldwma(s_space, pws, r6, pmc_load_exc); - ldwma(s_space, pws, r7, pmc_load_exc); - ldwma(s_space, pws, r8, pmc_load_exc); - stwma(d_space, r5, pwd, pmc_store_exc); - stwma(d_space, r6, pwd, pmc_store_exc); - stwma(d_space, r7, pwd, pmc_store_exc); - stwma(d_space, r8, pwd, pmc_store_exc); - len -= 8*sizeof(unsigned int); - } - - while (len >= 4*sizeof(unsigned int)) { - register unsigned int r1,r2,r3,r4; - ldwma(s_space, pws, r1, pmc_load_exc); - ldwma(s_space, pws, r2, pmc_load_exc); - ldwma(s_space, pws, r3, pmc_load_exc); - ldwma(s_space, pws, r4, pmc_load_exc); - stwma(d_space, r1, pwd, pmc_store_exc); - stwma(d_space, r2, pwd, pmc_store_exc); - stwma(d_space, r3, pwd, pmc_store_exc); - stwma(d_space, r4, pwd, pmc_store_exc); - len -= 4*sizeof(unsigned int); - } - - pcs = (unsigned char *)pws; - pcd = (unsigned char *)pwd; - -byte_copy: - while (len) { - /* *pcd++ = *pcs++; */ - ldbma(s_space, pcs, t3, pmc_load_exc); - stbma(d_space, t3, pcd, pmc_store_exc); - len--; - } - - return PA_MEMCPY_OK; - -unaligned_copy: - /* possibly we are aligned on a word, but not on a double... */ - if (likely((t1 & (sizeof(unsigned int)-1)) == 0)) { - t2 = src & (sizeof(unsigned int) - 1); - - if (unlikely(t2 != 0)) { - t2 = sizeof(unsigned int) - t2; - while (t2) { - /* *pcd++ = *pcs++; */ - ldbma(s_space, pcs, t3, pmc_load_exc); - stbma(d_space, t3, pcd, pmc_store_exc); - len--; - t2--; - } - } - - pws = (unsigned int *)pcs; - pwd = (unsigned int *)pcd; - goto word_copy; - } - - /* Align the destination. */ - if (unlikely((dst & (sizeof(unsigned int) - 1)) != 0)) { - t2 = sizeof(unsigned int) - (dst & (sizeof(unsigned int) - 1)); - while (t2) { - /* *pcd++ = *pcs++; */ - ldbma(s_space, pcs, t3, pmc_load_exc); - stbma(d_space, t3, pcd, pmc_store_exc); - len--; - t2--; - } - dst = (unsigned long)pcd; - src = (unsigned long)pcs; - } - - ret = copy_dstaligned(dst, src, len / sizeof(unsigned int)); - if (ret) - return ret; - - pcs += (len & -sizeof(unsigned int)); - pcd += (len & -sizeof(unsigned int)); - len %= sizeof(unsigned int); - - preserve_branch(handle_load_error); - preserve_branch(handle_store_error); - - goto byte_copy; - -handle_load_error: - __asm__ __volatile__ ("pmc_load_exc:\n"); - return PA_MEMCPY_LOAD_ERROR; - -handle_store_error: - __asm__ __volatile__ ("pmc_store_exc:\n"); - return PA_MEMCPY_STORE_ERROR; -} - - /* Returns 0 for success, otherwise, returns number of bytes not transferred. */ -static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) -{ - unsigned long ret, fault_addr, reference; - struct exception_data *d; - - ret = pa_memcpy_internal(dstp, srcp, len); - if (likely(ret == PA_MEMCPY_OK)) - return 0; - - /* if a load or store fault occured we can get the faulty addr */ - d = this_cpu_ptr(&exception_data); - fault_addr = d->fault_addr; - - /* error in load or store? */ - if (ret == PA_MEMCPY_LOAD_ERROR) - reference = (unsigned long) srcp; - else - reference = (unsigned long) dstp; - - DPRINTF("pa_memcpy: fault type = %lu, len=%lu fault_addr=%lu ref=%lu\n", - ret, len, fault_addr, reference); +extern unsigned long pa_memcpy(void *dst, const void *src, + unsigned long len); - if (fault_addr >= reference) - return len - (fault_addr - reference); - else - return len; -} - -#ifdef __KERNEL__ -unsigned long __copy_to_user(void __user *dst, const void *src, - unsigned long len) +unsigned long raw_copy_to_user(void __user *dst, const void *src, + unsigned long len) { mtsp(get_kernel_space(), 1); mtsp(get_user_space(), 2); return pa_memcpy((void __force *)dst, src, len); } -EXPORT_SYMBOL(__copy_to_user); +EXPORT_SYMBOL(raw_copy_to_user); -unsigned long __copy_from_user(void *dst, const void __user *src, +unsigned long raw_copy_from_user(void *dst, const void __user *src, unsigned long len) { mtsp(get_user_space(), 1); mtsp(get_kernel_space(), 2); return pa_memcpy(dst, (void __force *)src, len); } -EXPORT_SYMBOL(__copy_from_user); +EXPORT_SYMBOL(raw_copy_from_user); -unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len) +unsigned long raw_copy_in_user(void __user *dst, const void __user *src, unsigned long len) { mtsp(get_user_space(), 1); mtsp(get_user_space(), 2); @@ -523,7 +70,7 @@ void * memcpy(void * dst,const void *src, size_t count) return dst; } -EXPORT_SYMBOL(copy_in_user); +EXPORT_SYMBOL(raw_copy_in_user); EXPORT_SYMBOL(memcpy); long probe_kernel_read(void *dst, const void *src, size_t size) @@ -537,5 +84,3 @@ long probe_kernel_read(void *dst, const void *src, size_t size) return __probe_kernel_read(dst, src, size); } - -#endif diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index deab89a8915a..32ec22146141 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -150,6 +150,23 @@ int fixup_exception(struct pt_regs *regs) d->fault_space = regs->isr; d->fault_addr = regs->ior; + /* + * Fix up get_user() and put_user(). + * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() sets the least-significant + * bit in the relative address of the fixup routine to indicate + * that %r8 should be loaded with -EFAULT to report a userspace + * access error. + */ + if (fix->fixup & 1) { + regs->gr[8] = -EFAULT; + + /* zero target register for get_user() */ + if (parisc_acctyp(0, regs->iir) == VM_READ) { + int treg = regs->iir & 0x1f; + regs->gr[treg] = 0; + } + } + regs->iaoq[0] = (unsigned long)&fix->fixup + fix->fixup; regs->iaoq[0] &= ~3; /* diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 494091762bd7..053382616533 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -80,93 +80,98 @@ config ARCH_HAS_DMA_SET_COHERENT_MASK config PPC bool default y - select BUILDTIME_EXTABLE_SORT + # + # Please keep this list sorted alphabetically. + # + select ARCH_HAS_DEVMEM_IS_ALLOWED + select ARCH_HAS_DMA_SET_COHERENT_MASK + select ARCH_HAS_ELF_RANDOMIZE + select ARCH_HAS_GCOV_PROFILE_ALL + select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE + select ARCH_HAS_SG_CHAIN + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST + select ARCH_HAS_UBSAN_SANITIZE_ALL + select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_SERIO + select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT + select ARCH_USE_BUILTIN_BSWAP + select ARCH_USE_CMPXCHG_LOCKREF if PPC64 + select ARCH_WANT_IPC_PARSE_VERSION select BINFMT_ELF - select ARCH_HAS_ELF_RANDOMIZE - select OF - select OF_EARLY_FLATTREE - select OF_RESERVED_MEM - select HAVE_FTRACE_MCOUNT_RECORD + select BUILDTIME_EXTABLE_SORT + select CLONE_BACKWARDS + select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN + select EDAC_ATOMIC_SCRUB + select EDAC_SUPPORT + select GENERIC_ATOMIC64 if PPC32 + select GENERIC_CLOCKEVENTS + select GENERIC_CLOCKEVENTS_BROADCAST if SMP + select GENERIC_CMOS_UPDATE + select GENERIC_CPU_AUTOPROBE + select GENERIC_IRQ_SHOW + select GENERIC_IRQ_SHOW_LEVEL + select GENERIC_SMP_IDLE_THREAD + select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER + select GENERIC_TIME_VSYSCALL_OLD + select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_KGDB + select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TRACEHOOK + select HAVE_CBPF_JIT if !PPC64 + select HAVE_CONTEXT_TRACKING if PPC64 + select HAVE_DEBUG_KMEMLEAK + select HAVE_DEBUG_STACKOVERFLOW + select HAVE_DMA_API_DEBUG select HAVE_DYNAMIC_FTRACE - select HAVE_DYNAMIC_FTRACE_WITH_REGS if MPROFILE_KERNEL - select HAVE_FUNCTION_TRACER + select HAVE_DYNAMIC_FTRACE_WITH_REGS if MPROFILE_KERNEL + select HAVE_EBPF_JIT if PPC64 + select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) + select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_TRACER select HAVE_GCC_PLUGINS - select SYSCTL_EXCEPTION_TRACE - select VIRT_TO_BUS if !PPC64 + select HAVE_GENERIC_RCU_GUP + select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx) select HAVE_IDE select HAVE_IOREMAP_PROT - select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) + select HAVE_IRQ_EXIT_ON_IRQ_STACK + select HAVE_KERNEL_GZIP select HAVE_KPROBES - select HAVE_OPTPROBES if PPC64 - select HAVE_ARCH_KGDB select HAVE_KRETPROBES - select HAVE_ARCH_TRACEHOOK + select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP - select HAVE_DMA_API_DEBUG + select HAVE_MOD_ARCH_SPECIFIC + select HAVE_NMI if PERF_EVENTS select HAVE_OPROFILE - select HAVE_DEBUG_KMEMLEAK - select ARCH_HAS_SG_CHAIN - select GENERIC_ATOMIC64 if PPC32 + select HAVE_OPTPROBES if PPC64 select HAVE_PERF_EVENTS + select HAVE_PERF_EVENTS_NMI if PPC64 select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP + select HAVE_RCU_TABLE_FREE if SMP select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx) - select ARCH_WANT_IPC_PARSE_VERSION - select SPARSE_IRQ + select HAVE_SYSCALL_TRACEPOINTS + select HAVE_VIRT_CPU_ACCOUNTING select IRQ_DOMAIN - select GENERIC_IRQ_SHOW - select GENERIC_IRQ_SHOW_LEVEL select IRQ_FORCED_THREADING - select HAVE_RCU_TABLE_FREE if SMP - select HAVE_SYSCALL_TRACEPOINTS - select HAVE_CBPF_JIT if !PPC64 - select HAVE_EBPF_JIT if PPC64 - select HAVE_ARCH_JUMP_LABEL - select ARCH_HAVE_NMI_SAFE_CMPXCHG - select ARCH_HAS_GCOV_PROFILE_ALL - select GENERIC_SMP_IDLE_THREAD - select GENERIC_CMOS_UPDATE - select GENERIC_TIME_VSYSCALL_OLD - select GENERIC_CLOCKEVENTS - select GENERIC_CLOCKEVENTS_BROADCAST if SMP - select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER - select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA - select CLONE_BACKWARDS - select ARCH_USE_BUILTIN_BSWAP - select OLD_SIGSUSPEND - select OLD_SIGACTION if PPC32 - select HAVE_DEBUG_STACKOVERFLOW - select HAVE_IRQ_EXIT_ON_IRQ_STACK - select ARCH_USE_CMPXCHG_LOCKREF if PPC64 - select HAVE_ARCH_AUDITSYSCALL - select ARCH_SUPPORTS_ATOMIC_RMW - select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN select NO_BOOTMEM - select HAVE_GENERIC_RCU_GUP - select HAVE_PERF_EVENTS_NMI if PPC64 - select HAVE_NMI if PERF_EVENTS - select EDAC_SUPPORT - select EDAC_ATOMIC_SCRUB - select ARCH_HAS_DMA_SET_COHERENT_MASK - select ARCH_HAS_DEVMEM_IS_ALLOWED - select HAVE_ARCH_SECCOMP_FILTER - select ARCH_HAS_UBSAN_SANITIZE_ALL - select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT - select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS - select GENERIC_CPU_AUTOPROBE - select HAVE_VIRT_CPU_ACCOUNTING - select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE - select HAVE_ARCH_HARDENED_USERCOPY - select HAVE_KERNEL_GZIP - select HAVE_CONTEXT_TRACKING if PPC64 + select OF + select OF_EARLY_FLATTREE + select OF_RESERVED_MEM + select OLD_SIGACTION if PPC32 + select OLD_SIGSUSPEND + select SPARSE_IRQ + select SYSCTL_EXCEPTION_TRACE + select VIRT_TO_BUS if !PPC64 + # + # Please keep this list sorted alphabetically. + # config GENERIC_CSUM def_bool n diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 31286fa7873c..19b0d1a81959 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -72,8 +72,15 @@ GNUTARGET := powerpc MULTIPLEWORD := -mmultiple endif -cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian) +ifdef CONFIG_PPC64 +cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1) +cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mcall-aixdesc) +aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1) +aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2 +endif + cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian +cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian) ifneq ($(cc-name),clang) cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mno-strict-align endif @@ -113,7 +120,9 @@ ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2,$(call cc-option,-mcall-aixdesc)) AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2) else +CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv1) CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcall-aixdesc) +AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv1) endif CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,$(call cc-option,-mminimal-toc)) CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mno-pointers-to-nested-functions) diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 861e72109df2..f080abfc2f83 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -68,6 +68,7 @@ SECTIONS } #ifdef CONFIG_PPC64_BOOT_WRAPPER + . = ALIGN(256); .got : { __toc_start = .; diff --git a/arch/powerpc/configs/85xx-hw.config b/arch/powerpc/configs/85xx-hw.config index 528ff0e714e6..c03d0fb16665 100644 --- a/arch/powerpc/configs/85xx-hw.config +++ b/arch/powerpc/configs/85xx-hw.config @@ -16,9 +16,8 @@ CONFIG_DAVICOM_PHY=y CONFIG_DMADEVICES=y CONFIG_E1000E=y CONFIG_E1000=y -CONFIG_EDAC_MM_EDAC=y -CONFIG_EDAC_MPC85XX=y CONFIG_EDAC=y +CONFIG_EDAC_MPC85XX=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_LEGACY=y CONFIG_FB_FSL_DIU=y diff --git a/arch/powerpc/configs/85xx/ge_imp3a_defconfig b/arch/powerpc/configs/85xx/ge_imp3a_defconfig index c79283be5680..a917f7afb4f9 100644 --- a/arch/powerpc/configs/85xx/ge_imp3a_defconfig +++ b/arch/powerpc/configs/85xx/ge_imp3a_defconfig @@ -155,7 +155,6 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y CONFIG_USB_OHCI_HCD_PPC_OF_LE=y CONFIG_USB_STORAGE=y CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_MPC85XX=y CONFIG_RTC_CLASS=y # CONFIG_RTC_INTF_PROC is not set diff --git a/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig b/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig index dbd961de251e..72900b84d3e0 100644 --- a/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig +++ b/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig @@ -116,7 +116,6 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_CMOS=y diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 2d7fcbe047ac..aa564599e368 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -179,7 +179,6 @@ CONFIG_INFINIBAND_MTHCA=m CONFIG_INFINIBAND_IPOIB=m CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_CELL=y CONFIG_UIO=m CONFIG_EXT2_FS=y diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 5553c5ce4274..fe43ff47bd2f 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig @@ -142,7 +142,6 @@ CONFIG_USB_UHCI_HCD=y CONFIG_USB_SL811_HCD=y CONFIG_USB_STORAGE=y CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_PASEMI=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 4f1288b04303..f2e03f032041 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -262,7 +262,6 @@ CONFIG_INFINIBAND_IPOIB_CM=y CONFIG_INFINIBAND_SRP=m CONFIG_INFINIBAND_ISER=m CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_PASEMI=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 11a3473f9e2e..6340e6c53c54 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig @@ -173,7 +173,6 @@ CONFIG_INFINIBAND_MTHCA=m CONFIG_INFINIBAND_IPOIB=m CONFIG_INFINIBAND_ISER=m CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_FS_DAX=y diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index 1d2d69dd6409..18d0d60dadbf 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -988,8 +988,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_ACCESSIBILITY=y CONFIG_A11Y_BRAILLE_CONSOLE=y -CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC=m CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set CONFIG_RTC_DRV_DS1307=m diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile index 87f40454bad3..67eca3af9fc7 100644 --- a/arch/powerpc/crypto/Makefile +++ b/arch/powerpc/crypto/Makefile @@ -10,6 +10,8 @@ obj-$(CONFIG_CRYPTO_SHA1_PPC) += sha1-powerpc.o obj-$(CONFIG_CRYPTO_SHA1_PPC_SPE) += sha1-ppc-spe.o obj-$(CONFIG_CRYPTO_SHA256_PPC_SPE) += sha256-ppc-spe.o obj-$(CONFIG_CRYPTO_CRC32C_VPMSUM) += crc32c-vpmsum.o +obj-$(CONFIG_CRYPTO_CRCT10DIF_VPMSUM) += crct10dif-vpmsum.o +obj-$(CONFIG_CRYPTO_VPMSUM_TESTER) += crc-vpmsum_test.o aes-ppc-spe-y := aes-spe-core.o aes-spe-keys.o aes-tab-4k.o aes-spe-modes.o aes-spe-glue.o md5-ppc-y := md5-asm.o md5-glue.o @@ -17,3 +19,4 @@ sha1-powerpc-y := sha1-powerpc-asm.o sha1.o sha1-ppc-spe-y := sha1-spe-asm.o sha1-spe-glue.o sha256-ppc-spe-y := sha256-spe-asm.o sha256-spe-glue.o crc32c-vpmsum-y := crc32c-vpmsum_asm.o crc32c-vpmsum_glue.o +crct10dif-vpmsum-y := crct10dif-vpmsum_asm.o crct10dif-vpmsum_glue.o diff --git a/arch/powerpc/crypto/crc-vpmsum_test.c b/arch/powerpc/crypto/crc-vpmsum_test.c new file mode 100644 index 000000000000..0153a9c6f4af --- /dev/null +++ b/arch/powerpc/crypto/crc-vpmsum_test.c @@ -0,0 +1,137 @@ +/* + * CRC vpmsum tester + * Copyright 2017 Daniel Axtens, IBM Corporation. + * + * 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/crc-t10dif.h> +#include <linux/crc32.h> +#include <crypto/internal/hash.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/cpufeature.h> +#include <asm/switch_to.h> + +static unsigned long iterations = 10000; + +#define MAX_CRC_LENGTH 65535 + + +static int __init crc_test_init(void) +{ + u16 crc16 = 0, verify16 = 0; + u32 crc32 = 0, verify32 = 0; + __le32 verify32le = 0; + unsigned char *data; + unsigned long i; + int ret; + + struct crypto_shash *crct10dif_tfm; + struct crypto_shash *crc32c_tfm; + + if (!cpu_has_feature(CPU_FTR_ARCH_207S)) + return -ENODEV; + + data = kmalloc(MAX_CRC_LENGTH, GFP_KERNEL); + if (!data) + return -ENOMEM; + + crct10dif_tfm = crypto_alloc_shash("crct10dif", 0, 0); + + if (IS_ERR(crct10dif_tfm)) { + pr_err("Error allocating crc-t10dif\n"); + goto free_buf; + } + + crc32c_tfm = crypto_alloc_shash("crc32c", 0, 0); + + if (IS_ERR(crc32c_tfm)) { + pr_err("Error allocating crc32c\n"); + goto free_16; + } + + do { + SHASH_DESC_ON_STACK(crct10dif_shash, crct10dif_tfm); + SHASH_DESC_ON_STACK(crc32c_shash, crc32c_tfm); + + crct10dif_shash->tfm = crct10dif_tfm; + ret = crypto_shash_init(crct10dif_shash); + + if (ret) { + pr_err("Error initing crc-t10dif\n"); + goto free_32; + } + + + crc32c_shash->tfm = crc32c_tfm; + ret = crypto_shash_init(crc32c_shash); + + if (ret) { + pr_err("Error initing crc32c\n"); + goto free_32; + } + + pr_info("crc-vpmsum_test begins, %lu iterations\n", iterations); + for (i=0; i<iterations; i++) { + size_t len, offset; + + get_random_bytes(data, MAX_CRC_LENGTH); + get_random_bytes(&len, sizeof(len)); + get_random_bytes(&offset, sizeof(offset)); + + len %= MAX_CRC_LENGTH; + offset &= 15; + if (len <= offset) + continue; + len -= offset; + + crypto_shash_update(crct10dif_shash, data+offset, len); + crypto_shash_final(crct10dif_shash, (u8 *)(&crc16)); + verify16 = crc_t10dif_generic(verify16, data+offset, len); + + + if (crc16 != verify16) { + pr_err("FAILURE in CRC16: got 0x%04x expected 0x%04x (len %lu)\n", + crc16, verify16, len); + break; + } + + crypto_shash_update(crc32c_shash, data+offset, len); + crypto_shash_final(crc32c_shash, (u8 *)(&crc32)); + verify32 = le32_to_cpu(verify32le); + verify32le = ~cpu_to_le32(__crc32c_le(~verify32, data+offset, len)); + if (crc32 != (u32)verify32le) { + pr_err("FAILURE in CRC32: got 0x%08x expected 0x%08x (len %lu)\n", + crc32, verify32, len); + break; + } + } + pr_info("crc-vpmsum_test done, completed %lu iterations\n", i); + } while (0); + +free_32: + crypto_free_shash(crc32c_tfm); + +free_16: + crypto_free_shash(crct10dif_tfm); + +free_buf: + kfree(data); + + return 0; +} + +static void __exit crc_test_exit(void) {} + +module_init(crc_test_init); +module_exit(crc_test_exit); +module_param(iterations, long, 0400); + +MODULE_AUTHOR("Daniel Axtens <dja@axtens.net>"); +MODULE_DESCRIPTION("Vector polynomial multiply-sum CRC tester"); +MODULE_LICENSE("GPL"); diff --git a/arch/powerpc/crypto/crc32-vpmsum_core.S b/arch/powerpc/crypto/crc32-vpmsum_core.S new file mode 100644 index 000000000000..aadb59c96a27 --- /dev/null +++ b/arch/powerpc/crypto/crc32-vpmsum_core.S @@ -0,0 +1,755 @@ +/* + * Core of the accelerated CRC algorithm. + * In your file, define the constants and CRC_FUNCTION_NAME + * Then include this file. + * + * Calculate the checksum of data that is 16 byte aligned and a multiple of + * 16 bytes. + * + * The first step is to reduce it to 1024 bits. We do this in 8 parallel + * chunks in order to mask the latency of the vpmsum instructions. If we + * have more than 32 kB of data to checksum we repeat this step multiple + * times, passing in the previous 1024 bits. + * + * The next step is to reduce the 1024 bits to 64 bits. This step adds + * 32 bits of 0s to the end - this matches what a CRC does. We just + * calculate constants that land the data in this 32 bits. + * + * We then use fixed point Barrett reduction to compute a mod n over GF(2) + * for n = CRC using POWER8 instructions. We use x = 32. + * + * http://en.wikipedia.org/wiki/Barrett_reduction + * + * Copyright (C) 2015 Anton Blanchard <anton@au.ibm.com>, IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. +*/ + +#include <asm/ppc_asm.h> +#include <asm/ppc-opcode.h> + +#define MAX_SIZE 32768 + + .text + +#if defined(__BIG_ENDIAN__) && defined(REFLECT) +#define BYTESWAP_DATA +#elif defined(__LITTLE_ENDIAN__) && !defined(REFLECT) +#define BYTESWAP_DATA +#else +#undef BYTESWAP_DATA +#endif + +#define off16 r25 +#define off32 r26 +#define off48 r27 +#define off64 r28 +#define off80 r29 +#define off96 r30 +#define off112 r31 + +#define const1 v24 +#define const2 v25 + +#define byteswap v26 +#define mask_32bit v27 +#define mask_64bit v28 +#define zeroes v29 + +#ifdef BYTESWAP_DATA +#define VPERM(A, B, C, D) vperm A, B, C, D +#else +#define VPERM(A, B, C, D) +#endif + +/* unsigned int CRC_FUNCTION_NAME(unsigned int crc, void *p, unsigned long len) */ +FUNC_START(CRC_FUNCTION_NAME) + std r31,-8(r1) + std r30,-16(r1) + std r29,-24(r1) + std r28,-32(r1) + std r27,-40(r1) + std r26,-48(r1) + std r25,-56(r1) + + li off16,16 + li off32,32 + li off48,48 + li off64,64 + li off80,80 + li off96,96 + li off112,112 + li r0,0 + + /* Enough room for saving 10 non volatile VMX registers */ + subi r6,r1,56+10*16 + subi r7,r1,56+2*16 + + stvx v20,0,r6 + stvx v21,off16,r6 + stvx v22,off32,r6 + stvx v23,off48,r6 + stvx v24,off64,r6 + stvx v25,off80,r6 + stvx v26,off96,r6 + stvx v27,off112,r6 + stvx v28,0,r7 + stvx v29,off16,r7 + + mr r10,r3 + + vxor zeroes,zeroes,zeroes + vspltisw v0,-1 + + vsldoi mask_32bit,zeroes,v0,4 + vsldoi mask_64bit,zeroes,v0,8 + + /* Get the initial value into v8 */ + vxor v8,v8,v8 + MTVRD(v8, R3) +#ifdef REFLECT + vsldoi v8,zeroes,v8,8 /* shift into bottom 32 bits */ +#else + vsldoi v8,v8,zeroes,4 /* shift into top 32 bits */ +#endif + +#ifdef BYTESWAP_DATA + addis r3,r2,.byteswap_constant@toc@ha + addi r3,r3,.byteswap_constant@toc@l + + lvx byteswap,0,r3 + addi r3,r3,16 +#endif + + cmpdi r5,256 + blt .Lshort + + rldicr r6,r5,0,56 + + /* Checksum in blocks of MAX_SIZE */ +1: lis r7,MAX_SIZE@h + ori r7,r7,MAX_SIZE@l + mr r9,r7 + cmpd r6,r7 + bgt 2f + mr r7,r6 +2: subf r6,r7,r6 + + /* our main loop does 128 bytes at a time */ + srdi r7,r7,7 + + /* + * Work out the offset into the constants table to start at. Each + * constant is 16 bytes, and it is used against 128 bytes of input + * data - 128 / 16 = 8 + */ + sldi r8,r7,4 + srdi r9,r9,3 + subf r8,r8,r9 + + /* We reduce our final 128 bytes in a separate step */ + addi r7,r7,-1 + mtctr r7 + + addis r3,r2,.constants@toc@ha + addi r3,r3,.constants@toc@l + + /* Find the start of our constants */ + add r3,r3,r8 + + /* zero v0-v7 which will contain our checksums */ + vxor v0,v0,v0 + vxor v1,v1,v1 + vxor v2,v2,v2 + vxor v3,v3,v3 + vxor v4,v4,v4 + vxor v5,v5,v5 + vxor v6,v6,v6 + vxor v7,v7,v7 + + lvx const1,0,r3 + + /* + * If we are looping back to consume more data we use the values + * already in v16-v23. + */ + cmpdi r0,1 + beq 2f + + /* First warm up pass */ + lvx v16,0,r4 + lvx v17,off16,r4 + VPERM(v16,v16,v16,byteswap) + VPERM(v17,v17,v17,byteswap) + lvx v18,off32,r4 + lvx v19,off48,r4 + VPERM(v18,v18,v18,byteswap) + VPERM(v19,v19,v19,byteswap) + lvx v20,off64,r4 + lvx v21,off80,r4 + VPERM(v20,v20,v20,byteswap) + VPERM(v21,v21,v21,byteswap) + lvx v22,off96,r4 + lvx v23,off112,r4 + VPERM(v22,v22,v22,byteswap) + VPERM(v23,v23,v23,byteswap) + addi r4,r4,8*16 + + /* xor in initial value */ + vxor v16,v16,v8 + +2: bdz .Lfirst_warm_up_done + + addi r3,r3,16 + lvx const2,0,r3 + + /* Second warm up pass */ + VPMSUMD(v8,v16,const1) + lvx v16,0,r4 + VPERM(v16,v16,v16,byteswap) + ori r2,r2,0 + + VPMSUMD(v9,v17,const1) + lvx v17,off16,r4 + VPERM(v17,v17,v17,byteswap) + ori r2,r2,0 + + VPMSUMD(v10,v18,const1) + lvx v18,off32,r4 + VPERM(v18,v18,v18,byteswap) + ori r2,r2,0 + + VPMSUMD(v11,v19,const1) + lvx v19,off48,r4 + VPERM(v19,v19,v19,byteswap) + ori r2,r2,0 + + VPMSUMD(v12,v20,const1) + lvx v20,off64,r4 + VPERM(v20,v20,v20,byteswap) + ori r2,r2,0 + + VPMSUMD(v13,v21,const1) + lvx v21,off80,r4 + VPERM(v21,v21,v21,byteswap) + ori r2,r2,0 + + VPMSUMD(v14,v22,const1) + lvx v22,off96,r4 + VPERM(v22,v22,v22,byteswap) + ori r2,r2,0 + + VPMSUMD(v15,v23,const1) + lvx v23,off112,r4 + VPERM(v23,v23,v23,byteswap) + + addi r4,r4,8*16 + + bdz .Lfirst_cool_down + + /* + * main loop. We modulo schedule it such that it takes three iterations + * to complete - first iteration load, second iteration vpmsum, third + * iteration xor. + */ + .balign 16 +4: lvx const1,0,r3 + addi r3,r3,16 + ori r2,r2,0 + + vxor v0,v0,v8 + VPMSUMD(v8,v16,const2) + lvx v16,0,r4 + VPERM(v16,v16,v16,byteswap) + ori r2,r2,0 + + vxor v1,v1,v9 + VPMSUMD(v9,v17,const2) + lvx v17,off16,r4 + VPERM(v17,v17,v17,byteswap) + ori r2,r2,0 + + vxor v2,v2,v10 + VPMSUMD(v10,v18,const2) + lvx v18,off32,r4 + VPERM(v18,v18,v18,byteswap) + ori r2,r2,0 + + vxor v3,v3,v11 + VPMSUMD(v11,v19,const2) + lvx v19,off48,r4 + VPERM(v19,v19,v19,byteswap) + lvx const2,0,r3 + ori r2,r2,0 + + vxor v4,v4,v12 + VPMSUMD(v12,v20,const1) + lvx v20,off64,r4 + VPERM(v20,v20,v20,byteswap) + ori r2,r2,0 + + vxor v5,v5,v13 + VPMSUMD(v13,v21,const1) + lvx v21,off80,r4 + VPERM(v21,v21,v21,byteswap) + ori r2,r2,0 + + vxor v6,v6,v14 + VPMSUMD(v14,v22,const1) + lvx v22,off96,r4 + VPERM(v22,v22,v22,byteswap) + ori r2,r2,0 + + vxor v7,v7,v15 + VPMSUMD(v15,v23,const1) + lvx v23,off112,r4 + VPERM(v23,v23,v23,byteswap) + + addi r4,r4,8*16 + + bdnz 4b + +.Lfirst_cool_down: + /* First cool down pass */ + lvx const1,0,r3 + addi r3,r3,16 + + vxor v0,v0,v8 + VPMSUMD(v8,v16,const1) + ori r2,r2,0 + + vxor v1,v1,v9 + VPMSUMD(v9,v17,const1) + ori r2,r2,0 + + vxor v2,v2,v10 + VPMSUMD(v10,v18,const1) + ori r2,r2,0 + + vxor v3,v3,v11 + VPMSUMD(v11,v19,const1) + ori r2,r2,0 + + vxor v4,v4,v12 + VPMSUMD(v12,v20,const1) + ori r2,r2,0 + + vxor v5,v5,v13 + VPMSUMD(v13,v21,const1) + ori r2,r2,0 + + vxor v6,v6,v14 + VPMSUMD(v14,v22,const1) + ori r2,r2,0 + + vxor v7,v7,v15 + VPMSUMD(v15,v23,const1) + ori r2,r2,0 + +.Lsecond_cool_down: + /* Second cool down pass */ + vxor v0,v0,v8 + vxor v1,v1,v9 + vxor v2,v2,v10 + vxor v3,v3,v11 + vxor v4,v4,v12 + vxor v5,v5,v13 + vxor v6,v6,v14 + vxor v7,v7,v15 + +#ifdef REFLECT + /* + * vpmsumd produces a 96 bit result in the least significant bits + * of the register. Since we are bit reflected we have to shift it + * left 32 bits so it occupies the least significant bits in the + * bit reflected domain. + */ + vsldoi v0,v0,zeroes,4 + vsldoi v1,v1,zeroes,4 + vsldoi v2,v2,zeroes,4 + vsldoi v3,v3,zeroes,4 + vsldoi v4,v4,zeroes,4 + vsldoi v5,v5,zeroes,4 + vsldoi v6,v6,zeroes,4 + vsldoi v7,v7,zeroes,4 +#endif + + /* xor with last 1024 bits */ + lvx v8,0,r4 + lvx v9,off16,r4 + VPERM(v8,v8,v8,byteswap) + VPERM(v9,v9,v9,byteswap) + lvx v10,off32,r4 + lvx v11,off48,r4 + VPERM(v10,v10,v10,byteswap) + VPERM(v11,v11,v11,byteswap) + lvx v12,off64,r4 + lvx v13,off80,r4 + VPERM(v12,v12,v12,byteswap) + VPERM(v13,v13,v13,byteswap) + lvx v14,off96,r4 + lvx v15,off112,r4 + VPERM(v14,v14,v14,byteswap) + VPERM(v15,v15,v15,byteswap) + + addi r4,r4,8*16 + + vxor v16,v0,v8 + vxor v17,v1,v9 + vxor v18,v2,v10 + vxor v19,v3,v11 + vxor v20,v4,v12 + vxor v21,v5,v13 + vxor v22,v6,v14 + vxor v23,v7,v15 + + li r0,1 + cmpdi r6,0 + addi r6,r6,128 + bne 1b + + /* Work out how many bytes we have left */ + andi. r5,r5,127 + + /* Calculate where in the constant table we need to start */ + subfic r6,r5,128 + add r3,r3,r6 + + /* How many 16 byte chunks are in the tail */ + srdi r7,r5,4 + mtctr r7 + + /* + * Reduce the previously calculated 1024 bits to 64 bits, shifting + * 32 bits to include the trailing 32 bits of zeros + */ + lvx v0,0,r3 + lvx v1,off16,r3 + lvx v2,off32,r3 + lvx v3,off48,r3 + lvx v4,off64,r3 + lvx v5,off80,r3 + lvx v6,off96,r3 + lvx v7,off112,r3 + addi r3,r3,8*16 + + VPMSUMW(v0,v16,v0) + VPMSUMW(v1,v17,v1) + VPMSUMW(v2,v18,v2) + VPMSUMW(v3,v19,v3) + VPMSUMW(v4,v20,v4) + VPMSUMW(v5,v21,v5) + VPMSUMW(v6,v22,v6) + VPMSUMW(v7,v23,v7) + + /* Now reduce the tail (0 - 112 bytes) */ + cmpdi r7,0 + beq 1f + + lvx v16,0,r4 + lvx v17,0,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + bdz 1f + + lvx v16,off16,r4 + lvx v17,off16,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + bdz 1f + + lvx v16,off32,r4 + lvx v17,off32,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + bdz 1f + + lvx v16,off48,r4 + lvx v17,off48,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + bdz 1f + + lvx v16,off64,r4 + lvx v17,off64,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + bdz 1f + + lvx v16,off80,r4 + lvx v17,off80,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + bdz 1f + + lvx v16,off96,r4 + lvx v17,off96,r3 + VPERM(v16,v16,v16,byteswap) + VPMSUMW(v16,v16,v17) + vxor v0,v0,v16 + + /* Now xor all the parallel chunks together */ +1: vxor v0,v0,v1 + vxor v2,v2,v3 + vxor v4,v4,v5 + vxor v6,v6,v7 + + vxor v0,v0,v2 + vxor v4,v4,v6 + + vxor v0,v0,v4 + +.Lbarrett_reduction: + /* Barrett constants */ + addis r3,r2,.barrett_constants@toc@ha + addi r3,r3,.barrett_constants@toc@l + + lvx const1,0,r3 + lvx const2,off16,r3 + + vsldoi v1,v0,v0,8 + vxor v0,v0,v1 /* xor two 64 bit results together */ + +#ifdef REFLECT + /* shift left one bit */ + vspltisb v1,1 + vsl v0,v0,v1 +#endif + + vand v0,v0,mask_64bit +#ifndef REFLECT + /* + * Now for the Barrett reduction algorithm. The idea is to calculate q, + * the multiple of our polynomial that we need to subtract. By + * doing the computation 2x bits higher (ie 64 bits) and shifting the + * result back down 2x bits, we round down to the nearest multiple. + */ + VPMSUMD(v1,v0,const1) /* ma */ + vsldoi v1,zeroes,v1,8 /* q = floor(ma/(2^64)) */ + VPMSUMD(v1,v1,const2) /* qn */ + vxor v0,v0,v1 /* a - qn, subtraction is xor in GF(2) */ + + /* + * Get the result into r3. We need to shift it left 8 bytes: + * V0 [ 0 1 2 X ] + * V0 [ 0 X 2 3 ] + */ + vsldoi v0,v0,zeroes,8 /* shift result into top 64 bits */ +#else + /* + * The reflected version of Barrett reduction. Instead of bit + * reflecting our data (which is expensive to do), we bit reflect our + * constants and our algorithm, which means the intermediate data in + * our vector registers goes from 0-63 instead of 63-0. We can reflect + * the algorithm because we don't carry in mod 2 arithmetic. + */ + vand v1,v0,mask_32bit /* bottom 32 bits of a */ + VPMSUMD(v1,v1,const1) /* ma */ + vand v1,v1,mask_32bit /* bottom 32bits of ma */ + VPMSUMD(v1,v1,const2) /* qn */ + vxor v0,v0,v1 /* a - qn, subtraction is xor in GF(2) */ + + /* + * Since we are bit reflected, the result (ie the low 32 bits) is in + * the high 32 bits. We just need to shift it left 4 bytes + * V0 [ 0 1 X 3 ] + * V0 [ 0 X 2 3 ] + */ + vsldoi v0,v0,zeroes,4 /* shift result into top 64 bits of */ +#endif + + /* Get it into r3 */ + MFVRD(R3, v0) + +.Lout: + subi r6,r1,56+10*16 + subi r7,r1,56+2*16 + + lvx v20,0,r6 + lvx v21,off16,r6 + lvx v22,off32,r6 + lvx v23,off48,r6 + lvx v24,off64,r6 + lvx v25,off80,r6 + lvx v26,off96,r6 + lvx v27,off112,r6 + lvx v28,0,r7 + lvx v29,off16,r7 + + ld r31,-8(r1) + ld r30,-16(r1) + ld r29,-24(r1) + ld r28,-32(r1) + ld r27,-40(r1) + ld r26,-48(r1) + ld r25,-56(r1) + + blr + +.Lfirst_warm_up_done: + lvx const1,0,r3 + addi r3,r3,16 + + VPMSUMD(v8,v16,const1) + VPMSUMD(v9,v17,const1) + VPMSUMD(v10,v18,const1) + VPMSUMD(v11,v19,const1) + VPMSUMD(v12,v20,const1) + VPMSUMD(v13,v21,const1) + VPMSUMD(v14,v22,const1) + VPMSUMD(v15,v23,const1) + + b .Lsecond_cool_down + +.Lshort: + cmpdi r5,0 + beq .Lzero + + addis r3,r2,.short_constants@toc@ha + addi r3,r3,.short_constants@toc@l + + /* Calculate where in the constant table we need to start */ + subfic r6,r5,256 + add r3,r3,r6 + + /* How many 16 byte chunks? */ + srdi r7,r5,4 + mtctr r7 + + vxor v19,v19,v19 + vxor v20,v20,v20 + + lvx v0,0,r4 + lvx v16,0,r3 + VPERM(v0,v0,v16,byteswap) + vxor v0,v0,v8 /* xor in initial value */ + VPMSUMW(v0,v0,v16) + bdz .Lv0 + + lvx v1,off16,r4 + lvx v17,off16,r3 + VPERM(v1,v1,v17,byteswap) + VPMSUMW(v1,v1,v17) + bdz .Lv1 + + lvx v2,off32,r4 + lvx v16,off32,r3 + VPERM(v2,v2,v16,byteswap) + VPMSUMW(v2,v2,v16) + bdz .Lv2 + + lvx v3,off48,r4 + lvx v17,off48,r3 + VPERM(v3,v3,v17,byteswap) + VPMSUMW(v3,v3,v17) + bdz .Lv3 + + lvx v4,off64,r4 + lvx v16,off64,r3 + VPERM(v4,v4,v16,byteswap) + VPMSUMW(v4,v4,v16) + bdz .Lv4 + + lvx v5,off80,r4 + lvx v17,off80,r3 + VPERM(v5,v5,v17,byteswap) + VPMSUMW(v5,v5,v17) + bdz .Lv5 + + lvx v6,off96,r4 + lvx v16,off96,r3 + VPERM(v6,v6,v16,byteswap) + VPMSUMW(v6,v6,v16) + bdz .Lv6 + + lvx v7,off112,r4 + lvx v17,off112,r3 + VPERM(v7,v7,v17,byteswap) + VPMSUMW(v7,v7,v17) + bdz .Lv7 + + addi r3,r3,128 + addi r4,r4,128 + + lvx v8,0,r4 + lvx v16,0,r3 + VPERM(v8,v8,v16,byteswap) + VPMSUMW(v8,v8,v16) + bdz .Lv8 + + lvx v9,off16,r4 + lvx v17,off16,r3 + VPERM(v9,v9,v17,byteswap) + VPMSUMW(v9,v9,v17) + bdz .Lv9 + + lvx v10,off32,r4 + lvx v16,off32,r3 + VPERM(v10,v10,v16,byteswap) + VPMSUMW(v10,v10,v16) + bdz .Lv10 + + lvx v11,off48,r4 + lvx v17,off48,r3 + VPERM(v11,v11,v17,byteswap) + VPMSUMW(v11,v11,v17) + bdz .Lv11 + + lvx v12,off64,r4 + lvx v16,off64,r3 + VPERM(v12,v12,v16,byteswap) + VPMSUMW(v12,v12,v16) + bdz .Lv12 + + lvx v13,off80,r4 + lvx v17,off80,r3 + VPERM(v13,v13,v17,byteswap) + VPMSUMW(v13,v13,v17) + bdz .Lv13 + + lvx v14,off96,r4 + lvx v16,off96,r3 + VPERM(v14,v14,v16,byteswap) + VPMSUMW(v14,v14,v16) + bdz .Lv14 + + lvx v15,off112,r4 + lvx v17,off112,r3 + VPERM(v15,v15,v17,byteswap) + VPMSUMW(v15,v15,v17) + +.Lv15: vxor v19,v19,v15 +.Lv14: vxor v20,v20,v14 +.Lv13: vxor v19,v19,v13 +.Lv12: vxor v20,v20,v12 +.Lv11: vxor v19,v19,v11 +.Lv10: vxor v20,v20,v10 +.Lv9: vxor v19,v19,v9 +.Lv8: vxor v20,v20,v8 +.Lv7: vxor v19,v19,v7 +.Lv6: vxor v20,v20,v6 +.Lv5: vxor v19,v19,v5 +.Lv4: vxor v20,v20,v4 +.Lv3: vxor v19,v19,v3 +.Lv2: vxor v20,v20,v2 +.Lv1: vxor v19,v19,v1 +.Lv0: vxor v20,v20,v0 + + vxor v0,v19,v20 + + b .Lbarrett_reduction + +.Lzero: + mr r3,r10 + b .Lout + +FUNC_END(CRC_FUNCTION_NAME) diff --git a/arch/powerpc/crypto/crc32c-vpmsum_asm.S b/arch/powerpc/crypto/crc32c-vpmsum_asm.S index dc640b212299..d2bea48051a0 100644 --- a/arch/powerpc/crypto/crc32c-vpmsum_asm.S +++ b/arch/powerpc/crypto/crc32c-vpmsum_asm.S @@ -1,20 +1,5 @@ /* - * Calculate the checksum of data that is 16 byte aligned and a multiple of - * 16 bytes. - * - * The first step is to reduce it to 1024 bits. We do this in 8 parallel - * chunks in order to mask the latency of the vpmsum instructions. If we - * have more than 32 kB of data to checksum we repeat this step multiple - * times, passing in the previous 1024 bits. - * - * The next step is to reduce the 1024 bits to 64 bits. This step adds - * 32 bits of 0s to the end - this matches what a CRC does. We just - * calculate constants that land the data in this 32 bits. - * - * We then use fixed point Barrett reduction to compute a mod n over GF(2) - * for n = CRC using POWER8 instructions. We use x = 32. - * - * http://en.wikipedia.org/wiki/Barrett_reduction + * Calculate a crc32c with vpmsum acceleration * * Copyright (C) 2015 Anton Blanchard <anton@au.ibm.com>, IBM * @@ -23,9 +8,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <asm/ppc_asm.h> -#include <asm/ppc-opcode.h> - .section .rodata .balign 16 @@ -33,7 +15,6 @@ /* byte reverse permute constant */ .octa 0x0F0E0D0C0B0A09080706050403020100 -#define MAX_SIZE 32768 .constants: /* Reduce 262144 kbits to 1024 bits */ @@ -860,694 +841,6 @@ /* 33 bit reflected Barrett constant n */ .octa 0x00000000000000000000000105ec76f1 - .text - -#if defined(__BIG_ENDIAN__) -#define BYTESWAP_DATA -#else -#undef BYTESWAP_DATA -#endif - -#define off16 r25 -#define off32 r26 -#define off48 r27 -#define off64 r28 -#define off80 r29 -#define off96 r30 -#define off112 r31 - -#define const1 v24 -#define const2 v25 - -#define byteswap v26 -#define mask_32bit v27 -#define mask_64bit v28 -#define zeroes v29 - -#ifdef BYTESWAP_DATA -#define VPERM(A, B, C, D) vperm A, B, C, D -#else -#define VPERM(A, B, C, D) -#endif - -/* unsigned int __crc32c_vpmsum(unsigned int crc, void *p, unsigned long len) */ -FUNC_START(__crc32c_vpmsum) - std r31,-8(r1) - std r30,-16(r1) - std r29,-24(r1) - std r28,-32(r1) - std r27,-40(r1) - std r26,-48(r1) - std r25,-56(r1) - - li off16,16 - li off32,32 - li off48,48 - li off64,64 - li off80,80 - li off96,96 - li off112,112 - li r0,0 - - /* Enough room for saving 10 non volatile VMX registers */ - subi r6,r1,56+10*16 - subi r7,r1,56+2*16 - - stvx v20,0,r6 - stvx v21,off16,r6 - stvx v22,off32,r6 - stvx v23,off48,r6 - stvx v24,off64,r6 - stvx v25,off80,r6 - stvx v26,off96,r6 - stvx v27,off112,r6 - stvx v28,0,r7 - stvx v29,off16,r7 - - mr r10,r3 - - vxor zeroes,zeroes,zeroes - vspltisw v0,-1 - - vsldoi mask_32bit,zeroes,v0,4 - vsldoi mask_64bit,zeroes,v0,8 - - /* Get the initial value into v8 */ - vxor v8,v8,v8 - MTVRD(v8, R3) - vsldoi v8,zeroes,v8,8 /* shift into bottom 32 bits */ - -#ifdef BYTESWAP_DATA - addis r3,r2,.byteswap_constant@toc@ha - addi r3,r3,.byteswap_constant@toc@l - - lvx byteswap,0,r3 - addi r3,r3,16 -#endif - - cmpdi r5,256 - blt .Lshort - - rldicr r6,r5,0,56 - - /* Checksum in blocks of MAX_SIZE */ -1: lis r7,MAX_SIZE@h - ori r7,r7,MAX_SIZE@l - mr r9,r7 - cmpd r6,r7 - bgt 2f - mr r7,r6 -2: subf r6,r7,r6 - - /* our main loop does 128 bytes at a time */ - srdi r7,r7,7 - - /* - * Work out the offset into the constants table to start at. Each - * constant is 16 bytes, and it is used against 128 bytes of input - * data - 128 / 16 = 8 - */ - sldi r8,r7,4 - srdi r9,r9,3 - subf r8,r8,r9 - - /* We reduce our final 128 bytes in a separate step */ - addi r7,r7,-1 - mtctr r7 - - addis r3,r2,.constants@toc@ha - addi r3,r3,.constants@toc@l - - /* Find the start of our constants */ - add r3,r3,r8 - - /* zero v0-v7 which will contain our checksums */ - vxor v0,v0,v0 - vxor v1,v1,v1 - vxor v2,v2,v2 - vxor v3,v3,v3 - vxor v4,v4,v4 - vxor v5,v5,v5 - vxor v6,v6,v6 - vxor v7,v7,v7 - - lvx const1,0,r3 - - /* - * If we are looping back to consume more data we use the values - * already in v16-v23. - */ - cmpdi r0,1 - beq 2f - - /* First warm up pass */ - lvx v16,0,r4 - lvx v17,off16,r4 - VPERM(v16,v16,v16,byteswap) - VPERM(v17,v17,v17,byteswap) - lvx v18,off32,r4 - lvx v19,off48,r4 - VPERM(v18,v18,v18,byteswap) - VPERM(v19,v19,v19,byteswap) - lvx v20,off64,r4 - lvx v21,off80,r4 - VPERM(v20,v20,v20,byteswap) - VPERM(v21,v21,v21,byteswap) - lvx v22,off96,r4 - lvx v23,off112,r4 - VPERM(v22,v22,v22,byteswap) - VPERM(v23,v23,v23,byteswap) - addi r4,r4,8*16 - - /* xor in initial value */ - vxor v16,v16,v8 - -2: bdz .Lfirst_warm_up_done - - addi r3,r3,16 - lvx const2,0,r3 - - /* Second warm up pass */ - VPMSUMD(v8,v16,const1) - lvx v16,0,r4 - VPERM(v16,v16,v16,byteswap) - ori r2,r2,0 - - VPMSUMD(v9,v17,const1) - lvx v17,off16,r4 - VPERM(v17,v17,v17,byteswap) - ori r2,r2,0 - - VPMSUMD(v10,v18,const1) - lvx v18,off32,r4 - VPERM(v18,v18,v18,byteswap) - ori r2,r2,0 - - VPMSUMD(v11,v19,const1) - lvx v19,off48,r4 - VPERM(v19,v19,v19,byteswap) - ori r2,r2,0 - - VPMSUMD(v12,v20,const1) - lvx v20,off64,r4 - VPERM(v20,v20,v20,byteswap) - ori r2,r2,0 - - VPMSUMD(v13,v21,const1) - lvx v21,off80,r4 - VPERM(v21,v21,v21,byteswap) - ori r2,r2,0 - - VPMSUMD(v14,v22,const1) - lvx v22,off96,r4 - VPERM(v22,v22,v22,byteswap) - ori r2,r2,0 - - VPMSUMD(v15,v23,const1) - lvx v23,off112,r4 - VPERM(v23,v23,v23,byteswap) - - addi r4,r4,8*16 - - bdz .Lfirst_cool_down - - /* - * main loop. We modulo schedule it such that it takes three iterations - * to complete - first iteration load, second iteration vpmsum, third - * iteration xor. - */ - .balign 16 -4: lvx const1,0,r3 - addi r3,r3,16 - ori r2,r2,0 - - vxor v0,v0,v8 - VPMSUMD(v8,v16,const2) - lvx v16,0,r4 - VPERM(v16,v16,v16,byteswap) - ori r2,r2,0 - - vxor v1,v1,v9 - VPMSUMD(v9,v17,const2) - lvx v17,off16,r4 - VPERM(v17,v17,v17,byteswap) - ori r2,r2,0 - - vxor v2,v2,v10 - VPMSUMD(v10,v18,const2) - lvx v18,off32,r4 - VPERM(v18,v18,v18,byteswap) - ori r2,r2,0 - - vxor v3,v3,v11 - VPMSUMD(v11,v19,const2) - lvx v19,off48,r4 - VPERM(v19,v19,v19,byteswap) - lvx const2,0,r3 - ori r2,r2,0 - - vxor v4,v4,v12 - VPMSUMD(v12,v20,const1) - lvx v20,off64,r4 - VPERM(v20,v20,v20,byteswap) - ori r2,r2,0 - - vxor v5,v5,v13 - VPMSUMD(v13,v21,const1) - lvx v21,off80,r4 - VPERM(v21,v21,v21,byteswap) - ori r2,r2,0 - - vxor v6,v6,v14 - VPMSUMD(v14,v22,const1) - lvx v22,off96,r4 - VPERM(v22,v22,v22,byteswap) - ori r2,r2,0 - - vxor v7,v7,v15 - VPMSUMD(v15,v23,const1) - lvx v23,off112,r4 - VPERM(v23,v23,v23,byteswap) - - addi r4,r4,8*16 - - bdnz 4b - -.Lfirst_cool_down: - /* First cool down pass */ - lvx const1,0,r3 - addi r3,r3,16 - - vxor v0,v0,v8 - VPMSUMD(v8,v16,const1) - ori r2,r2,0 - - vxor v1,v1,v9 - VPMSUMD(v9,v17,const1) - ori r2,r2,0 - - vxor v2,v2,v10 - VPMSUMD(v10,v18,const1) - ori r2,r2,0 - - vxor v3,v3,v11 - VPMSUMD(v11,v19,const1) - ori r2,r2,0 - - vxor v4,v4,v12 - VPMSUMD(v12,v20,const1) - ori r2,r2,0 - - vxor v5,v5,v13 - VPMSUMD(v13,v21,const1) - ori r2,r2,0 - - vxor v6,v6,v14 - VPMSUMD(v14,v22,const1) - ori r2,r2,0 - - vxor v7,v7,v15 - VPMSUMD(v15,v23,const1) - ori r2,r2,0 - -.Lsecond_cool_down: - /* Second cool down pass */ - vxor v0,v0,v8 - vxor v1,v1,v9 - vxor v2,v2,v10 - vxor v3,v3,v11 - vxor v4,v4,v12 - vxor v5,v5,v13 - vxor v6,v6,v14 - vxor v7,v7,v15 - - /* - * vpmsumd produces a 96 bit result in the least significant bits - * of the register. Since we are bit reflected we have to shift it - * left 32 bits so it occupies the least significant bits in the - * bit reflected domain. - */ - vsldoi v0,v0,zeroes,4 - vsldoi v1,v1,zeroes,4 - vsldoi v2,v2,zeroes,4 - vsldoi v3,v3,zeroes,4 - vsldoi v4,v4,zeroes,4 - vsldoi v5,v5,zeroes,4 - vsldoi v6,v6,zeroes,4 - vsldoi v7,v7,zeroes,4 - - /* xor with last 1024 bits */ - lvx v8,0,r4 - lvx v9,off16,r4 - VPERM(v8,v8,v8,byteswap) - VPERM(v9,v9,v9,byteswap) - lvx v10,off32,r4 - lvx v11,off48,r4 - VPERM(v10,v10,v10,byteswap) - VPERM(v11,v11,v11,byteswap) - lvx v12,off64,r4 - lvx v13,off80,r4 - VPERM(v12,v12,v12,byteswap) - VPERM(v13,v13,v13,byteswap) - lvx v14,off96,r4 - lvx v15,off112,r4 - VPERM(v14,v14,v14,byteswap) - VPERM(v15,v15,v15,byteswap) - - addi r4,r4,8*16 - - vxor v16,v0,v8 - vxor v17,v1,v9 - vxor v18,v2,v10 - vxor v19,v3,v11 - vxor v20,v4,v12 - vxor v21,v5,v13 - vxor v22,v6,v14 - vxor v23,v7,v15 - - li r0,1 - cmpdi r6,0 - addi r6,r6,128 - bne 1b - - /* Work out how many bytes we have left */ - andi. r5,r5,127 - - /* Calculate where in the constant table we need to start */ - subfic r6,r5,128 - add r3,r3,r6 - - /* How many 16 byte chunks are in the tail */ - srdi r7,r5,4 - mtctr r7 - - /* - * Reduce the previously calculated 1024 bits to 64 bits, shifting - * 32 bits to include the trailing 32 bits of zeros - */ - lvx v0,0,r3 - lvx v1,off16,r3 - lvx v2,off32,r3 - lvx v3,off48,r3 - lvx v4,off64,r3 - lvx v5,off80,r3 - lvx v6,off96,r3 - lvx v7,off112,r3 - addi r3,r3,8*16 - - VPMSUMW(v0,v16,v0) - VPMSUMW(v1,v17,v1) - VPMSUMW(v2,v18,v2) - VPMSUMW(v3,v19,v3) - VPMSUMW(v4,v20,v4) - VPMSUMW(v5,v21,v5) - VPMSUMW(v6,v22,v6) - VPMSUMW(v7,v23,v7) - - /* Now reduce the tail (0 - 112 bytes) */ - cmpdi r7,0 - beq 1f - - lvx v16,0,r4 - lvx v17,0,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - bdz 1f - - lvx v16,off16,r4 - lvx v17,off16,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - bdz 1f - - lvx v16,off32,r4 - lvx v17,off32,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - bdz 1f - - lvx v16,off48,r4 - lvx v17,off48,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - bdz 1f - - lvx v16,off64,r4 - lvx v17,off64,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - bdz 1f - - lvx v16,off80,r4 - lvx v17,off80,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - bdz 1f - - lvx v16,off96,r4 - lvx v17,off96,r3 - VPERM(v16,v16,v16,byteswap) - VPMSUMW(v16,v16,v17) - vxor v0,v0,v16 - - /* Now xor all the parallel chunks together */ -1: vxor v0,v0,v1 - vxor v2,v2,v3 - vxor v4,v4,v5 - vxor v6,v6,v7 - - vxor v0,v0,v2 - vxor v4,v4,v6 - - vxor v0,v0,v4 - -.Lbarrett_reduction: - /* Barrett constants */ - addis r3,r2,.barrett_constants@toc@ha - addi r3,r3,.barrett_constants@toc@l - - lvx const1,0,r3 - lvx const2,off16,r3 - - vsldoi v1,v0,v0,8 - vxor v0,v0,v1 /* xor two 64 bit results together */ - - /* shift left one bit */ - vspltisb v1,1 - vsl v0,v0,v1 - - vand v0,v0,mask_64bit - - /* - * The reflected version of Barrett reduction. Instead of bit - * reflecting our data (which is expensive to do), we bit reflect our - * constants and our algorithm, which means the intermediate data in - * our vector registers goes from 0-63 instead of 63-0. We can reflect - * the algorithm because we don't carry in mod 2 arithmetic. - */ - vand v1,v0,mask_32bit /* bottom 32 bits of a */ - VPMSUMD(v1,v1,const1) /* ma */ - vand v1,v1,mask_32bit /* bottom 32bits of ma */ - VPMSUMD(v1,v1,const2) /* qn */ - vxor v0,v0,v1 /* a - qn, subtraction is xor in GF(2) */ - - /* - * Since we are bit reflected, the result (ie the low 32 bits) is in - * the high 32 bits. We just need to shift it left 4 bytes - * V0 [ 0 1 X 3 ] - * V0 [ 0 X 2 3 ] - */ - vsldoi v0,v0,zeroes,4 /* shift result into top 64 bits of */ - - /* Get it into r3 */ - MFVRD(R3, v0) - -.Lout: - subi r6,r1,56+10*16 - subi r7,r1,56+2*16 - - lvx v20,0,r6 - lvx v21,off16,r6 - lvx v22,off32,r6 - lvx v23,off48,r6 - lvx v24,off64,r6 - lvx v25,off80,r6 - lvx v26,off96,r6 - lvx v27,off112,r6 - lvx v28,0,r7 - lvx v29,off16,r7 - - ld r31,-8(r1) - ld r30,-16(r1) - ld r29,-24(r1) - ld r28,-32(r1) - ld r27,-40(r1) - ld r26,-48(r1) - ld r25,-56(r1) - - blr - -.Lfirst_warm_up_done: - lvx const1,0,r3 - addi r3,r3,16 - - VPMSUMD(v8,v16,const1) - VPMSUMD(v9,v17,const1) - VPMSUMD(v10,v18,const1) - VPMSUMD(v11,v19,const1) - VPMSUMD(v12,v20,const1) - VPMSUMD(v13,v21,const1) - VPMSUMD(v14,v22,const1) - VPMSUMD(v15,v23,const1) - - b .Lsecond_cool_down - -.Lshort: - cmpdi r5,0 - beq .Lzero - - addis r3,r2,.short_constants@toc@ha - addi r3,r3,.short_constants@toc@l - - /* Calculate where in the constant table we need to start */ - subfic r6,r5,256 - add r3,r3,r6 - - /* How many 16 byte chunks? */ - srdi r7,r5,4 - mtctr r7 - - vxor v19,v19,v19 - vxor v20,v20,v20 - - lvx v0,0,r4 - lvx v16,0,r3 - VPERM(v0,v0,v16,byteswap) - vxor v0,v0,v8 /* xor in initial value */ - VPMSUMW(v0,v0,v16) - bdz .Lv0 - - lvx v1,off16,r4 - lvx v17,off16,r3 - VPERM(v1,v1,v17,byteswap) - VPMSUMW(v1,v1,v17) - bdz .Lv1 - - lvx v2,off32,r4 - lvx v16,off32,r3 - VPERM(v2,v2,v16,byteswap) - VPMSUMW(v2,v2,v16) - bdz .Lv2 - - lvx v3,off48,r4 - lvx v17,off48,r3 - VPERM(v3,v3,v17,byteswap) - VPMSUMW(v3,v3,v17) - bdz .Lv3 - - lvx v4,off64,r4 - lvx v16,off64,r3 - VPERM(v4,v4,v16,byteswap) - VPMSUMW(v4,v4,v16) - bdz .Lv4 - - lvx v5,off80,r4 - lvx v17,off80,r3 - VPERM(v5,v5,v17,byteswap) - VPMSUMW(v5,v5,v17) - bdz .Lv5 - - lvx v6,off96,r4 - lvx v16,off96,r3 - VPERM(v6,v6,v16,byteswap) - VPMSUMW(v6,v6,v16) - bdz .Lv6 - - lvx v7,off112,r4 - lvx v17,off112,r3 - VPERM(v7,v7,v17,byteswap) - VPMSUMW(v7,v7,v17) - bdz .Lv7 - - addi r3,r3,128 - addi r4,r4,128 - - lvx v8,0,r4 - lvx v16,0,r3 - VPERM(v8,v8,v16,byteswap) - VPMSUMW(v8,v8,v16) - bdz .Lv8 - - lvx v9,off16,r4 - lvx v17,off16,r3 - VPERM(v9,v9,v17,byteswap) - VPMSUMW(v9,v9,v17) - bdz .Lv9 - - lvx v10,off32,r4 - lvx v16,off32,r3 - VPERM(v10,v10,v16,byteswap) - VPMSUMW(v10,v10,v16) - bdz .Lv10 - - lvx v11,off48,r4 - lvx v17,off48,r3 - VPERM(v11,v11,v17,byteswap) - VPMSUMW(v11,v11,v17) - bdz .Lv11 - - lvx v12,off64,r4 - lvx v16,off64,r3 - VPERM(v12,v12,v16,byteswap) - VPMSUMW(v12,v12,v16) - bdz .Lv12 - - lvx v13,off80,r4 - lvx v17,off80,r3 - VPERM(v13,v13,v17,byteswap) - VPMSUMW(v13,v13,v17) - bdz .Lv13 - - lvx v14,off96,r4 - lvx v16,off96,r3 - VPERM(v14,v14,v16,byteswap) - VPMSUMW(v14,v14,v16) - bdz .Lv14 - - lvx v15,off112,r4 - lvx v17,off112,r3 - VPERM(v15,v15,v17,byteswap) - VPMSUMW(v15,v15,v17) - -.Lv15: vxor v19,v19,v15 -.Lv14: vxor v20,v20,v14 -.Lv13: vxor v19,v19,v13 -.Lv12: vxor v20,v20,v12 -.Lv11: vxor v19,v19,v11 -.Lv10: vxor v20,v20,v10 -.Lv9: vxor v19,v19,v9 -.Lv8: vxor v20,v20,v8 -.Lv7: vxor v19,v19,v7 -.Lv6: vxor v20,v20,v6 -.Lv5: vxor v19,v19,v5 -.Lv4: vxor v20,v20,v4 -.Lv3: vxor v19,v19,v3 -.Lv2: vxor v20,v20,v2 -.Lv1: vxor v19,v19,v1 -.Lv0: vxor v20,v20,v0 - - vxor v0,v19,v20 - - b .Lbarrett_reduction - -.Lzero: - mr r3,r10 - b .Lout - -FUNC_END(__crc32_vpmsum) +#define CRC_FUNCTION_NAME __crc32c_vpmsum +#define REFLECT +#include "crc32-vpmsum_core.S" diff --git a/arch/powerpc/crypto/crc32c-vpmsum_glue.c b/arch/powerpc/crypto/crc32c-vpmsum_glue.c index 9fa046d56eba..f058e0c3e4d4 100644 --- a/arch/powerpc/crypto/crc32c-vpmsum_glue.c +++ b/arch/powerpc/crypto/crc32c-vpmsum_glue.c @@ -33,10 +33,13 @@ static u32 crc32c_vpmsum(u32 crc, unsigned char const *p, size_t len) } if (len & ~VMX_ALIGN_MASK) { + preempt_disable(); pagefault_disable(); enable_kernel_altivec(); crc = __crc32c_vpmsum(crc, p, len & ~VMX_ALIGN_MASK); + disable_kernel_altivec(); pagefault_enable(); + preempt_enable(); } tail = len & VMX_ALIGN_MASK; @@ -52,7 +55,7 @@ static int crc32c_vpmsum_cra_init(struct crypto_tfm *tfm) { u32 *key = crypto_tfm_ctx(tfm); - *key = 0; + *key = ~0; return 0; } diff --git a/arch/powerpc/crypto/crct10dif-vpmsum_asm.S b/arch/powerpc/crypto/crct10dif-vpmsum_asm.S new file mode 100644 index 000000000000..5e3d81a0af1b --- /dev/null +++ b/arch/powerpc/crypto/crct10dif-vpmsum_asm.S @@ -0,0 +1,850 @@ +/* + * Calculate a CRC T10DIF with vpmsum acceleration + * + * Constants generated by crc32-vpmsum, available at + * https://github.com/antonblanchard/crc32-vpmsum + * + * crc32-vpmsum is + * Copyright (C) 2015 Anton Blanchard <anton@au.ibm.com>, IBM + * and is available under the GPL v2 or later. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + .section .rodata +.balign 16 + +.byteswap_constant: + /* byte reverse permute constant */ + .octa 0x0F0E0D0C0B0A09080706050403020100 + +.constants: + + /* Reduce 262144 kbits to 1024 bits */ + /* x^261184 mod p(x), x^261120 mod p(x) */ + .octa 0x0000000056d300000000000052550000 + + /* x^260160 mod p(x), x^260096 mod p(x) */ + .octa 0x00000000ee67000000000000a1e40000 + + /* x^259136 mod p(x), x^259072 mod p(x) */ + .octa 0x0000000060830000000000004ad10000 + + /* x^258112 mod p(x), x^258048 mod p(x) */ + .octa 0x000000008cfe0000000000009ab40000 + + /* x^257088 mod p(x), x^257024 mod p(x) */ + .octa 0x000000003e93000000000000fdb50000 + + /* x^256064 mod p(x), x^256000 mod p(x) */ + .octa 0x000000003c2000000000000045480000 + + /* x^255040 mod p(x), x^254976 mod p(x) */ + .octa 0x00000000b1fc0000000000008d690000 + + /* x^254016 mod p(x), x^253952 mod p(x) */ + .octa 0x00000000f82b00000000000024ad0000 + + /* x^252992 mod p(x), x^252928 mod p(x) */ + .octa 0x0000000044420000000000009f1a0000 + + /* x^251968 mod p(x), x^251904 mod p(x) */ + .octa 0x00000000e88c00000000000066ec0000 + + /* x^250944 mod p(x), x^250880 mod p(x) */ + .octa 0x00000000385c000000000000c87d0000 + + /* x^249920 mod p(x), x^249856 mod p(x) */ + .octa 0x000000003227000000000000c8ff0000 + + /* x^248896 mod p(x), x^248832 mod p(x) */ + .octa 0x00000000a9a900000000000033440000 + + /* x^247872 mod p(x), x^247808 mod p(x) */ + .octa 0x00000000abaa00000000000066eb0000 + + /* x^246848 mod p(x), x^246784 mod p(x) */ + .octa 0x000000001ac3000000000000c4ef0000 + + /* x^245824 mod p(x), x^245760 mod p(x) */ + .octa 0x0000000063f000000000000056f30000 + + /* x^244800 mod p(x), x^244736 mod p(x) */ + .octa 0x0000000032cc00000000000002050000 + + /* x^243776 mod p(x), x^243712 mod p(x) */ + .octa 0x00000000f8b5000000000000568e0000 + + /* x^242752 mod p(x), x^242688 mod p(x) */ + .octa 0x000000008db100000000000064290000 + + /* x^241728 mod p(x), x^241664 mod p(x) */ + .octa 0x0000000059ca0000000000006b660000 + + /* x^240704 mod p(x), x^240640 mod p(x) */ + .octa 0x000000005f5c00000000000018f80000 + + /* x^239680 mod p(x), x^239616 mod p(x) */ + .octa 0x0000000061af000000000000b6090000 + + /* x^238656 mod p(x), x^238592 mod p(x) */ + .octa 0x00000000e29e000000000000099a0000 + + /* x^237632 mod p(x), x^237568 mod p(x) */ + .octa 0x000000000975000000000000a8360000 + + /* x^236608 mod p(x), x^236544 mod p(x) */ + .octa 0x0000000043900000000000004f570000 + + /* x^235584 mod p(x), x^235520 mod p(x) */ + .octa 0x00000000f9cd000000000000134c0000 + + /* x^234560 mod p(x), x^234496 mod p(x) */ + .octa 0x000000007c29000000000000ec380000 + + /* x^233536 mod p(x), x^233472 mod p(x) */ + .octa 0x000000004c6a000000000000b0d10000 + + /* x^232512 mod p(x), x^232448 mod p(x) */ + .octa 0x00000000e7290000000000007d3e0000 + + /* x^231488 mod p(x), x^231424 mod p(x) */ + .octa 0x00000000f1ab000000000000f0b20000 + + /* x^230464 mod p(x), x^230400 mod p(x) */ + .octa 0x0000000039db0000000000009c270000 + + /* x^229440 mod p(x), x^229376 mod p(x) */ + .octa 0x000000005e2800000000000092890000 + + /* x^228416 mod p(x), x^228352 mod p(x) */ + .octa 0x00000000d44e000000000000d5ee0000 + + /* x^227392 mod p(x), x^227328 mod p(x) */ + .octa 0x00000000cd0a00000000000041f50000 + + /* x^226368 mod p(x), x^226304 mod p(x) */ + .octa 0x00000000c5b400000000000010520000 + + /* x^225344 mod p(x), x^225280 mod p(x) */ + .octa 0x00000000fd2100000000000042170000 + + /* x^224320 mod p(x), x^224256 mod p(x) */ + .octa 0x000000002f2500000000000095c20000 + + /* x^223296 mod p(x), x^223232 mod p(x) */ + .octa 0x000000001b0100000000000001ce0000 + + /* x^222272 mod p(x), x^222208 mod p(x) */ + .octa 0x000000000d430000000000002aca0000 + + /* x^221248 mod p(x), x^221184 mod p(x) */ + .octa 0x0000000030a6000000000000385e0000 + + /* x^220224 mod p(x), x^220160 mod p(x) */ + .octa 0x00000000e37b0000000000006f7a0000 + + /* x^219200 mod p(x), x^219136 mod p(x) */ + .octa 0x00000000873600000000000024320000 + + /* x^218176 mod p(x), x^218112 mod p(x) */ + .octa 0x00000000e9fb000000000000bd9c0000 + + /* x^217152 mod p(x), x^217088 mod p(x) */ + .octa 0x000000003b9500000000000054bc0000 + + /* x^216128 mod p(x), x^216064 mod p(x) */ + .octa 0x00000000133e000000000000a4660000 + + /* x^215104 mod p(x), x^215040 mod p(x) */ + .octa 0x00000000784500000000000079930000 + + /* x^214080 mod p(x), x^214016 mod p(x) */ + .octa 0x00000000b9800000000000001bb80000 + + /* x^213056 mod p(x), x^212992 mod p(x) */ + .octa 0x00000000687600000000000024400000 + + /* x^212032 mod p(x), x^211968 mod p(x) */ + .octa 0x00000000aff300000000000029e10000 + + /* x^211008 mod p(x), x^210944 mod p(x) */ + .octa 0x0000000024b50000000000005ded0000 + + /* x^209984 mod p(x), x^209920 mod p(x) */ + .octa 0x0000000017e8000000000000b12e0000 + + /* x^208960 mod p(x), x^208896 mod p(x) */ + .octa 0x00000000128400000000000026d20000 + + /* x^207936 mod p(x), x^207872 mod p(x) */ + .octa 0x000000002115000000000000a32a0000 + + /* x^206912 mod p(x), x^206848 mod p(x) */ + .octa 0x000000009595000000000000a1210000 + + /* x^205888 mod p(x), x^205824 mod p(x) */ + .octa 0x00000000281e000000000000ee8b0000 + + /* x^204864 mod p(x), x^204800 mod p(x) */ + .octa 0x0000000006010000000000003d0d0000 + + /* x^203840 mod p(x), x^203776 mod p(x) */ + .octa 0x00000000e2b600000000000034e90000 + + /* x^202816 mod p(x), x^202752 mod p(x) */ + .octa 0x000000001bd40000000000004cdb0000 + + /* x^201792 mod p(x), x^201728 mod p(x) */ + .octa 0x00000000df2800000000000030e90000 + + /* x^200768 mod p(x), x^200704 mod p(x) */ + .octa 0x0000000049c200000000000042590000 + + /* x^199744 mod p(x), x^199680 mod p(x) */ + .octa 0x000000009b97000000000000df950000 + + /* x^198720 mod p(x), x^198656 mod p(x) */ + .octa 0x000000006184000000000000da7b0000 + + /* x^197696 mod p(x), x^197632 mod p(x) */ + .octa 0x00000000461700000000000012510000 + + /* x^196672 mod p(x), x^196608 mod p(x) */ + .octa 0x000000009b40000000000000f37e0000 + + /* x^195648 mod p(x), x^195584 mod p(x) */ + .octa 0x00000000eeb2000000000000ecf10000 + + /* x^194624 mod p(x), x^194560 mod p(x) */ + .octa 0x00000000b2e800000000000050f20000 + + /* x^193600 mod p(x), x^193536 mod p(x) */ + .octa 0x00000000f59a000000000000e0b30000 + + /* x^192576 mod p(x), x^192512 mod p(x) */ + .octa 0x00000000467f0000000000004d5a0000 + + /* x^191552 mod p(x), x^191488 mod p(x) */ + .octa 0x00000000da92000000000000bb010000 + + /* x^190528 mod p(x), x^190464 mod p(x) */ + .octa 0x000000001e1000000000000022a40000 + + /* x^189504 mod p(x), x^189440 mod p(x) */ + .octa 0x0000000058fe000000000000836f0000 + + /* x^188480 mod p(x), x^188416 mod p(x) */ + .octa 0x00000000b9ce000000000000d78d0000 + + /* x^187456 mod p(x), x^187392 mod p(x) */ + .octa 0x0000000022210000000000004f8d0000 + + /* x^186432 mod p(x), x^186368 mod p(x) */ + .octa 0x00000000744600000000000033760000 + + /* x^185408 mod p(x), x^185344 mod p(x) */ + .octa 0x000000001c2e000000000000a1e50000 + + /* x^184384 mod p(x), x^184320 mod p(x) */ + .octa 0x00000000dcc8000000000000a1a40000 + + /* x^183360 mod p(x), x^183296 mod p(x) */ + .octa 0x00000000910f00000000000019a20000 + + /* x^182336 mod p(x), x^182272 mod p(x) */ + .octa 0x0000000055d5000000000000f6ae0000 + + /* x^181312 mod p(x), x^181248 mod p(x) */ + .octa 0x00000000c8ba000000000000a7ac0000 + + /* x^180288 mod p(x), x^180224 mod p(x) */ + .octa 0x0000000031f8000000000000eea20000 + + /* x^179264 mod p(x), x^179200 mod p(x) */ + .octa 0x000000001966000000000000c4d90000 + + /* x^178240 mod p(x), x^178176 mod p(x) */ + .octa 0x00000000b9810000000000002b470000 + + /* x^177216 mod p(x), x^177152 mod p(x) */ + .octa 0x000000008303000000000000f7cf0000 + + /* x^176192 mod p(x), x^176128 mod p(x) */ + .octa 0x000000002ce500000000000035b30000 + + /* x^175168 mod p(x), x^175104 mod p(x) */ + .octa 0x000000002fae0000000000000c7c0000 + + /* x^174144 mod p(x), x^174080 mod p(x) */ + .octa 0x00000000f50c0000000000009edf0000 + + /* x^173120 mod p(x), x^173056 mod p(x) */ + .octa 0x00000000714f00000000000004cd0000 + + /* x^172096 mod p(x), x^172032 mod p(x) */ + .octa 0x00000000c161000000000000541b0000 + + /* x^171072 mod p(x), x^171008 mod p(x) */ + .octa 0x0000000021c8000000000000e2700000 + + /* x^170048 mod p(x), x^169984 mod p(x) */ + .octa 0x00000000b93d00000000000009a60000 + + /* x^169024 mod p(x), x^168960 mod p(x) */ + .octa 0x00000000fbcf000000000000761c0000 + + /* x^168000 mod p(x), x^167936 mod p(x) */ + .octa 0x0000000026350000000000009db30000 + + /* x^166976 mod p(x), x^166912 mod p(x) */ + .octa 0x00000000b64f0000000000003e9f0000 + + /* x^165952 mod p(x), x^165888 mod p(x) */ + .octa 0x00000000bd0e00000000000078590000 + + /* x^164928 mod p(x), x^164864 mod p(x) */ + .octa 0x00000000d9360000000000008bc80000 + + /* x^163904 mod p(x), x^163840 mod p(x) */ + .octa 0x000000002f140000000000008c9f0000 + + /* x^162880 mod p(x), x^162816 mod p(x) */ + .octa 0x000000006a270000000000006af70000 + + /* x^161856 mod p(x), x^161792 mod p(x) */ + .octa 0x000000006685000000000000e5210000 + + /* x^160832 mod p(x), x^160768 mod p(x) */ + .octa 0x0000000062da00000000000008290000 + + /* x^159808 mod p(x), x^159744 mod p(x) */ + .octa 0x00000000bb4b000000000000e4d00000 + + /* x^158784 mod p(x), x^158720 mod p(x) */ + .octa 0x00000000d2490000000000004ae10000 + + /* x^157760 mod p(x), x^157696 mod p(x) */ + .octa 0x00000000c85b00000000000000e70000 + + /* x^156736 mod p(x), x^156672 mod p(x) */ + .octa 0x00000000c37a00000000000015650000 + + /* x^155712 mod p(x), x^155648 mod p(x) */ + .octa 0x0000000018530000000000001c2f0000 + + /* x^154688 mod p(x), x^154624 mod p(x) */ + .octa 0x00000000b46600000000000037bd0000 + + /* x^153664 mod p(x), x^153600 mod p(x) */ + .octa 0x00000000439b00000000000012190000 + + /* x^152640 mod p(x), x^152576 mod p(x) */ + .octa 0x00000000b1260000000000005ece0000 + + /* x^151616 mod p(x), x^151552 mod p(x) */ + .octa 0x00000000d8110000000000002a5e0000 + + /* x^150592 mod p(x), x^150528 mod p(x) */ + .octa 0x00000000099f00000000000052330000 + + /* x^149568 mod p(x), x^149504 mod p(x) */ + .octa 0x00000000f9f9000000000000f9120000 + + /* x^148544 mod p(x), x^148480 mod p(x) */ + .octa 0x000000005cc00000000000000ddc0000 + + /* x^147520 mod p(x), x^147456 mod p(x) */ + .octa 0x00000000343b00000000000012200000 + + /* x^146496 mod p(x), x^146432 mod p(x) */ + .octa 0x000000009222000000000000d12b0000 + + /* x^145472 mod p(x), x^145408 mod p(x) */ + .octa 0x00000000d781000000000000eb2d0000 + + /* x^144448 mod p(x), x^144384 mod p(x) */ + .octa 0x000000000bf400000000000058970000 + + /* x^143424 mod p(x), x^143360 mod p(x) */ + .octa 0x00000000094200000000000013690000 + + /* x^142400 mod p(x), x^142336 mod p(x) */ + .octa 0x00000000d55100000000000051950000 + + /* x^141376 mod p(x), x^141312 mod p(x) */ + .octa 0x000000008f11000000000000954b0000 + + /* x^140352 mod p(x), x^140288 mod p(x) */ + .octa 0x00000000140f000000000000b29e0000 + + /* x^139328 mod p(x), x^139264 mod p(x) */ + .octa 0x00000000c6db000000000000db5d0000 + + /* x^138304 mod p(x), x^138240 mod p(x) */ + .octa 0x00000000715b000000000000dfaf0000 + + /* x^137280 mod p(x), x^137216 mod p(x) */ + .octa 0x000000000dea000000000000e3b60000 + + /* x^136256 mod p(x), x^136192 mod p(x) */ + .octa 0x000000006f94000000000000ddaf0000 + + /* x^135232 mod p(x), x^135168 mod p(x) */ + .octa 0x0000000024e1000000000000e4f70000 + + /* x^134208 mod p(x), x^134144 mod p(x) */ + .octa 0x000000008810000000000000aa110000 + + /* x^133184 mod p(x), x^133120 mod p(x) */ + .octa 0x0000000030c2000000000000a8e60000 + + /* x^132160 mod p(x), x^132096 mod p(x) */ + .octa 0x00000000e6d0000000000000ccf30000 + + /* x^131136 mod p(x), x^131072 mod p(x) */ + .octa 0x000000004da000000000000079bf0000 + + /* x^130112 mod p(x), x^130048 mod p(x) */ + .octa 0x000000007759000000000000b3a30000 + + /* x^129088 mod p(x), x^129024 mod p(x) */ + .octa 0x00000000597400000000000028790000 + + /* x^128064 mod p(x), x^128000 mod p(x) */ + .octa 0x000000007acd000000000000b5820000 + + /* x^127040 mod p(x), x^126976 mod p(x) */ + .octa 0x00000000e6e400000000000026ad0000 + + /* x^126016 mod p(x), x^125952 mod p(x) */ + .octa 0x000000006d49000000000000985b0000 + + /* x^124992 mod p(x), x^124928 mod p(x) */ + .octa 0x000000000f0800000000000011520000 + + /* x^123968 mod p(x), x^123904 mod p(x) */ + .octa 0x000000002c7f000000000000846c0000 + + /* x^122944 mod p(x), x^122880 mod p(x) */ + .octa 0x000000005ce7000000000000ae1d0000 + + /* x^121920 mod p(x), x^121856 mod p(x) */ + .octa 0x00000000d4cb000000000000e21d0000 + + /* x^120896 mod p(x), x^120832 mod p(x) */ + .octa 0x000000003a2300000000000019bb0000 + + /* x^119872 mod p(x), x^119808 mod p(x) */ + .octa 0x000000000e1700000000000095290000 + + /* x^118848 mod p(x), x^118784 mod p(x) */ + .octa 0x000000006e6400000000000050d20000 + + /* x^117824 mod p(x), x^117760 mod p(x) */ + .octa 0x000000008d5c0000000000000cd10000 + + /* x^116800 mod p(x), x^116736 mod p(x) */ + .octa 0x00000000ef310000000000007b570000 + + /* x^115776 mod p(x), x^115712 mod p(x) */ + .octa 0x00000000645d00000000000053d60000 + + /* x^114752 mod p(x), x^114688 mod p(x) */ + .octa 0x0000000018fc00000000000077510000 + + /* x^113728 mod p(x), x^113664 mod p(x) */ + .octa 0x000000000cb3000000000000a7b70000 + + /* x^112704 mod p(x), x^112640 mod p(x) */ + .octa 0x00000000991b000000000000d0780000 + + /* x^111680 mod p(x), x^111616 mod p(x) */ + .octa 0x00000000845a000000000000be3c0000 + + /* x^110656 mod p(x), x^110592 mod p(x) */ + .octa 0x00000000d3a9000000000000df020000 + + /* x^109632 mod p(x), x^109568 mod p(x) */ + .octa 0x0000000017d7000000000000063e0000 + + /* x^108608 mod p(x), x^108544 mod p(x) */ + .octa 0x000000007a860000000000008ab40000 + + /* x^107584 mod p(x), x^107520 mod p(x) */ + .octa 0x00000000fd7c000000000000c7bd0000 + + /* x^106560 mod p(x), x^106496 mod p(x) */ + .octa 0x00000000a56b000000000000efd60000 + + /* x^105536 mod p(x), x^105472 mod p(x) */ + .octa 0x0000000010e400000000000071380000 + + /* x^104512 mod p(x), x^104448 mod p(x) */ + .octa 0x00000000994500000000000004d30000 + + /* x^103488 mod p(x), x^103424 mod p(x) */ + .octa 0x00000000b83c0000000000003b0e0000 + + /* x^102464 mod p(x), x^102400 mod p(x) */ + .octa 0x00000000d6c10000000000008b020000 + + /* x^101440 mod p(x), x^101376 mod p(x) */ + .octa 0x000000009efc000000000000da940000 + + /* x^100416 mod p(x), x^100352 mod p(x) */ + .octa 0x000000005e87000000000000f9f70000 + + /* x^99392 mod p(x), x^99328 mod p(x) */ + .octa 0x000000006c9b00000000000045e40000 + + /* x^98368 mod p(x), x^98304 mod p(x) */ + .octa 0x00000000178a00000000000083940000 + + /* x^97344 mod p(x), x^97280 mod p(x) */ + .octa 0x00000000f0c8000000000000f0a00000 + + /* x^96320 mod p(x), x^96256 mod p(x) */ + .octa 0x00000000f699000000000000b74b0000 + + /* x^95296 mod p(x), x^95232 mod p(x) */ + .octa 0x00000000316d000000000000c1cf0000 + + /* x^94272 mod p(x), x^94208 mod p(x) */ + .octa 0x00000000987e00000000000072680000 + + /* x^93248 mod p(x), x^93184 mod p(x) */ + .octa 0x00000000acff000000000000e0ab0000 + + /* x^92224 mod p(x), x^92160 mod p(x) */ + .octa 0x00000000a1f6000000000000c5a80000 + + /* x^91200 mod p(x), x^91136 mod p(x) */ + .octa 0x0000000061bd000000000000cf690000 + + /* x^90176 mod p(x), x^90112 mod p(x) */ + .octa 0x00000000c9f2000000000000cbcc0000 + + /* x^89152 mod p(x), x^89088 mod p(x) */ + .octa 0x000000005a33000000000000de050000 + + /* x^88128 mod p(x), x^88064 mod p(x) */ + .octa 0x00000000e416000000000000ccd70000 + + /* x^87104 mod p(x), x^87040 mod p(x) */ + .octa 0x0000000058930000000000002f670000 + + /* x^86080 mod p(x), x^86016 mod p(x) */ + .octa 0x00000000a9d3000000000000152f0000 + + /* x^85056 mod p(x), x^84992 mod p(x) */ + .octa 0x00000000c114000000000000ecc20000 + + /* x^84032 mod p(x), x^83968 mod p(x) */ + .octa 0x00000000b9270000000000007c890000 + + /* x^83008 mod p(x), x^82944 mod p(x) */ + .octa 0x000000002e6000000000000006ee0000 + + /* x^81984 mod p(x), x^81920 mod p(x) */ + .octa 0x00000000dfc600000000000009100000 + + /* x^80960 mod p(x), x^80896 mod p(x) */ + .octa 0x000000004911000000000000ad4e0000 + + /* x^79936 mod p(x), x^79872 mod p(x) */ + .octa 0x00000000ae1b000000000000b04d0000 + + /* x^78912 mod p(x), x^78848 mod p(x) */ + .octa 0x0000000005fa000000000000e9900000 + + /* x^77888 mod p(x), x^77824 mod p(x) */ + .octa 0x0000000004a1000000000000cc6f0000 + + /* x^76864 mod p(x), x^76800 mod p(x) */ + .octa 0x00000000af73000000000000ed110000 + + /* x^75840 mod p(x), x^75776 mod p(x) */ + .octa 0x0000000082530000000000008f7e0000 + + /* x^74816 mod p(x), x^74752 mod p(x) */ + .octa 0x00000000cfdc000000000000594f0000 + + /* x^73792 mod p(x), x^73728 mod p(x) */ + .octa 0x00000000a6b6000000000000a8750000 + + /* x^72768 mod p(x), x^72704 mod p(x) */ + .octa 0x00000000fd76000000000000aa0c0000 + + /* x^71744 mod p(x), x^71680 mod p(x) */ + .octa 0x0000000006f500000000000071db0000 + + /* x^70720 mod p(x), x^70656 mod p(x) */ + .octa 0x0000000037ca000000000000ab0c0000 + + /* x^69696 mod p(x), x^69632 mod p(x) */ + .octa 0x00000000d7ab000000000000b7a00000 + + /* x^68672 mod p(x), x^68608 mod p(x) */ + .octa 0x00000000440800000000000090d30000 + + /* x^67648 mod p(x), x^67584 mod p(x) */ + .octa 0x00000000186100000000000054730000 + + /* x^66624 mod p(x), x^66560 mod p(x) */ + .octa 0x000000007368000000000000a3a20000 + + /* x^65600 mod p(x), x^65536 mod p(x) */ + .octa 0x0000000026d0000000000000f9040000 + + /* x^64576 mod p(x), x^64512 mod p(x) */ + .octa 0x00000000fe770000000000009c0a0000 + + /* x^63552 mod p(x), x^63488 mod p(x) */ + .octa 0x000000002cba000000000000d1e70000 + + /* x^62528 mod p(x), x^62464 mod p(x) */ + .octa 0x00000000f8bd0000000000005ac10000 + + /* x^61504 mod p(x), x^61440 mod p(x) */ + .octa 0x000000007372000000000000d68d0000 + + /* x^60480 mod p(x), x^60416 mod p(x) */ + .octa 0x00000000f37f00000000000089f60000 + + /* x^59456 mod p(x), x^59392 mod p(x) */ + .octa 0x00000000078400000000000008a90000 + + /* x^58432 mod p(x), x^58368 mod p(x) */ + .octa 0x00000000d3e400000000000042360000 + + /* x^57408 mod p(x), x^57344 mod p(x) */ + .octa 0x00000000eba800000000000092d50000 + + /* x^56384 mod p(x), x^56320 mod p(x) */ + .octa 0x00000000afbe000000000000b4d50000 + + /* x^55360 mod p(x), x^55296 mod p(x) */ + .octa 0x00000000d8ca000000000000c9060000 + + /* x^54336 mod p(x), x^54272 mod p(x) */ + .octa 0x00000000c2d00000000000008f4f0000 + + /* x^53312 mod p(x), x^53248 mod p(x) */ + .octa 0x00000000373200000000000028690000 + + /* x^52288 mod p(x), x^52224 mod p(x) */ + .octa 0x0000000046ae000000000000c3b30000 + + /* x^51264 mod p(x), x^51200 mod p(x) */ + .octa 0x00000000b243000000000000f8700000 + + /* x^50240 mod p(x), x^50176 mod p(x) */ + .octa 0x00000000f7f500000000000029eb0000 + + /* x^49216 mod p(x), x^49152 mod p(x) */ + .octa 0x000000000c7e000000000000fe730000 + + /* x^48192 mod p(x), x^48128 mod p(x) */ + .octa 0x00000000c38200000000000096000000 + + /* x^47168 mod p(x), x^47104 mod p(x) */ + .octa 0x000000008956000000000000683c0000 + + /* x^46144 mod p(x), x^46080 mod p(x) */ + .octa 0x00000000422d0000000000005f1e0000 + + /* x^45120 mod p(x), x^45056 mod p(x) */ + .octa 0x00000000ac0f0000000000006f810000 + + /* x^44096 mod p(x), x^44032 mod p(x) */ + .octa 0x00000000ce30000000000000031f0000 + + /* x^43072 mod p(x), x^43008 mod p(x) */ + .octa 0x000000003d43000000000000455a0000 + + /* x^42048 mod p(x), x^41984 mod p(x) */ + .octa 0x000000007ebe000000000000a6050000 + + /* x^41024 mod p(x), x^40960 mod p(x) */ + .octa 0x00000000976e00000000000077eb0000 + + /* x^40000 mod p(x), x^39936 mod p(x) */ + .octa 0x000000000872000000000000389c0000 + + /* x^38976 mod p(x), x^38912 mod p(x) */ + .octa 0x000000008979000000000000c7b20000 + + /* x^37952 mod p(x), x^37888 mod p(x) */ + .octa 0x000000005c1e0000000000001d870000 + + /* x^36928 mod p(x), x^36864 mod p(x) */ + .octa 0x00000000aebb00000000000045810000 + + /* x^35904 mod p(x), x^35840 mod p(x) */ + .octa 0x000000004f7e0000000000006d4a0000 + + /* x^34880 mod p(x), x^34816 mod p(x) */ + .octa 0x00000000ea98000000000000b9200000 + + /* x^33856 mod p(x), x^33792 mod p(x) */ + .octa 0x00000000f39600000000000022f20000 + + /* x^32832 mod p(x), x^32768 mod p(x) */ + .octa 0x000000000bc500000000000041ca0000 + + /* x^31808 mod p(x), x^31744 mod p(x) */ + .octa 0x00000000786400000000000078500000 + + /* x^30784 mod p(x), x^30720 mod p(x) */ + .octa 0x00000000be970000000000009e7e0000 + + /* x^29760 mod p(x), x^29696 mod p(x) */ + .octa 0x00000000dd6d000000000000a53c0000 + + /* x^28736 mod p(x), x^28672 mod p(x) */ + .octa 0x000000004c3f00000000000039340000 + + /* x^27712 mod p(x), x^27648 mod p(x) */ + .octa 0x0000000093a4000000000000b58e0000 + + /* x^26688 mod p(x), x^26624 mod p(x) */ + .octa 0x0000000050fb00000000000062d40000 + + /* x^25664 mod p(x), x^25600 mod p(x) */ + .octa 0x00000000f505000000000000a26f0000 + + /* x^24640 mod p(x), x^24576 mod p(x) */ + .octa 0x0000000064f900000000000065e60000 + + /* x^23616 mod p(x), x^23552 mod p(x) */ + .octa 0x00000000e8c2000000000000aad90000 + + /* x^22592 mod p(x), x^22528 mod p(x) */ + .octa 0x00000000720b000000000000a3b00000 + + /* x^21568 mod p(x), x^21504 mod p(x) */ + .octa 0x00000000e992000000000000d2680000 + + /* x^20544 mod p(x), x^20480 mod p(x) */ + .octa 0x000000009132000000000000cf4c0000 + + /* x^19520 mod p(x), x^19456 mod p(x) */ + .octa 0x00000000608a00000000000076610000 + + /* x^18496 mod p(x), x^18432 mod p(x) */ + .octa 0x000000009948000000000000fb9f0000 + + /* x^17472 mod p(x), x^17408 mod p(x) */ + .octa 0x00000000173000000000000003770000 + + /* x^16448 mod p(x), x^16384 mod p(x) */ + .octa 0x000000006fe300000000000004880000 + + /* x^15424 mod p(x), x^15360 mod p(x) */ + .octa 0x00000000e15300000000000056a70000 + + /* x^14400 mod p(x), x^14336 mod p(x) */ + .octa 0x0000000092d60000000000009dfd0000 + + /* x^13376 mod p(x), x^13312 mod p(x) */ + .octa 0x0000000002fd00000000000074c80000 + + /* x^12352 mod p(x), x^12288 mod p(x) */ + .octa 0x00000000c78b000000000000a3ec0000 + + /* x^11328 mod p(x), x^11264 mod p(x) */ + .octa 0x000000009262000000000000b3530000 + + /* x^10304 mod p(x), x^10240 mod p(x) */ + .octa 0x0000000084f200000000000047bf0000 + + /* x^9280 mod p(x), x^9216 mod p(x) */ + .octa 0x0000000067ee000000000000e97c0000 + + /* x^8256 mod p(x), x^8192 mod p(x) */ + .octa 0x00000000535b00000000000091e10000 + + /* x^7232 mod p(x), x^7168 mod p(x) */ + .octa 0x000000007ebb00000000000055060000 + + /* x^6208 mod p(x), x^6144 mod p(x) */ + .octa 0x00000000c6a1000000000000fd360000 + + /* x^5184 mod p(x), x^5120 mod p(x) */ + .octa 0x000000001be500000000000055860000 + + /* x^4160 mod p(x), x^4096 mod p(x) */ + .octa 0x00000000ae0e0000000000005bd00000 + + /* x^3136 mod p(x), x^3072 mod p(x) */ + .octa 0x0000000022040000000000008db20000 + + /* x^2112 mod p(x), x^2048 mod p(x) */ + .octa 0x00000000c9eb000000000000efe20000 + + /* x^1088 mod p(x), x^1024 mod p(x) */ + .octa 0x0000000039b400000000000051d10000 + +.short_constants: + + /* Reduce final 1024-2048 bits to 64 bits, shifting 32 bits to include the trailing 32 bits of zeros */ + /* x^2048 mod p(x), x^2016 mod p(x), x^1984 mod p(x), x^1952 mod p(x) */ + .octa 0xefe20000dccf00009440000033590000 + + /* x^1920 mod p(x), x^1888 mod p(x), x^1856 mod p(x), x^1824 mod p(x) */ + .octa 0xee6300002f3f000062180000e0ed0000 + + /* x^1792 mod p(x), x^1760 mod p(x), x^1728 mod p(x), x^1696 mod p(x) */ + .octa 0xcf5f000017ef0000ccbe000023d30000 + + /* x^1664 mod p(x), x^1632 mod p(x), x^1600 mod p(x), x^1568 mod p(x) */ + .octa 0x6d0c0000a30e00000920000042630000 + + /* x^1536 mod p(x), x^1504 mod p(x), x^1472 mod p(x), x^1440 mod p(x) */ + .octa 0x21d30000932b0000a7a00000efcc0000 + + /* x^1408 mod p(x), x^1376 mod p(x), x^1344 mod p(x), x^1312 mod p(x) */ + .octa 0x10be00000b310000666f00000d1c0000 + + /* x^1280 mod p(x), x^1248 mod p(x), x^1216 mod p(x), x^1184 mod p(x) */ + .octa 0x1f240000ce9e0000caad0000589e0000 + + /* x^1152 mod p(x), x^1120 mod p(x), x^1088 mod p(x), x^1056 mod p(x) */ + .octa 0x29610000d02b000039b400007cf50000 + + /* x^1024 mod p(x), x^992 mod p(x), x^960 mod p(x), x^928 mod p(x) */ + .octa 0x51d100009d9d00003c0e0000bfd60000 + + /* x^896 mod p(x), x^864 mod p(x), x^832 mod p(x), x^800 mod p(x) */ + .octa 0xda390000ceae000013830000713c0000 + + /* x^768 mod p(x), x^736 mod p(x), x^704 mod p(x), x^672 mod p(x) */ + .octa 0xb67800001e16000085c0000080a60000 + + /* x^640 mod p(x), x^608 mod p(x), x^576 mod p(x), x^544 mod p(x) */ + .octa 0x0db40000f7f90000371d0000e6580000 + + /* x^512 mod p(x), x^480 mod p(x), x^448 mod p(x), x^416 mod p(x) */ + .octa 0x87e70000044c0000aadb0000a4970000 + + /* x^384 mod p(x), x^352 mod p(x), x^320 mod p(x), x^288 mod p(x) */ + .octa 0x1f990000ad180000d8b30000e7b50000 + + /* x^256 mod p(x), x^224 mod p(x), x^192 mod p(x), x^160 mod p(x) */ + .octa 0xbe6c00006ee300004c1a000006df0000 + + /* x^128 mod p(x), x^96 mod p(x), x^64 mod p(x), x^32 mod p(x) */ + .octa 0xfb0b00002d560000136800008bb70000 + + +.barrett_constants: + /* Barrett constant m - (4^32)/n */ + .octa 0x000000000000000000000001f65a57f8 /* x^64 div p(x) */ + /* Barrett constant n */ + .octa 0x0000000000000000000000018bb70000 + +#define CRC_FUNCTION_NAME __crct10dif_vpmsum +#include "crc32-vpmsum_core.S" diff --git a/arch/powerpc/crypto/crct10dif-vpmsum_glue.c b/arch/powerpc/crypto/crct10dif-vpmsum_glue.c new file mode 100644 index 000000000000..02ea277863d1 --- /dev/null +++ b/arch/powerpc/crypto/crct10dif-vpmsum_glue.c @@ -0,0 +1,128 @@ +/* + * Calculate a CRC T10-DIF with vpmsum acceleration + * + * Copyright 2017, Daniel Axtens, IBM Corporation. + * [based on crc32c-vpmsum_glue.c] + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include <linux/crc-t10dif.h> +#include <crypto/internal/hash.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/cpufeature.h> +#include <asm/switch_to.h> + +#define VMX_ALIGN 16 +#define VMX_ALIGN_MASK (VMX_ALIGN-1) + +#define VECTOR_BREAKPOINT 64 + +u32 __crct10dif_vpmsum(u32 crc, unsigned char const *p, size_t len); + +static u16 crct10dif_vpmsum(u16 crci, unsigned char const *p, size_t len) +{ + unsigned int prealign; + unsigned int tail; + u32 crc = crci; + + if (len < (VECTOR_BREAKPOINT + VMX_ALIGN) || in_interrupt()) + return crc_t10dif_generic(crc, p, len); + + if ((unsigned long)p & VMX_ALIGN_MASK) { + prealign = VMX_ALIGN - ((unsigned long)p & VMX_ALIGN_MASK); + crc = crc_t10dif_generic(crc, p, prealign); + len -= prealign; + p += prealign; + } + + if (len & ~VMX_ALIGN_MASK) { + crc <<= 16; + preempt_disable(); + pagefault_disable(); + enable_kernel_altivec(); + crc = __crct10dif_vpmsum(crc, p, len & ~VMX_ALIGN_MASK); + disable_kernel_altivec(); + pagefault_enable(); + preempt_enable(); + crc >>= 16; + } + + tail = len & VMX_ALIGN_MASK; + if (tail) { + p += len & ~VMX_ALIGN_MASK; + crc = crc_t10dif_generic(crc, p, tail); + } + + return crc & 0xffff; +} + +static int crct10dif_vpmsum_init(struct shash_desc *desc) +{ + u16 *crc = shash_desc_ctx(desc); + + *crc = 0; + return 0; +} + +static int crct10dif_vpmsum_update(struct shash_desc *desc, const u8 *data, + unsigned int length) +{ + u16 *crc = shash_desc_ctx(desc); + + *crc = crct10dif_vpmsum(*crc, data, length); + + return 0; +} + + +static int crct10dif_vpmsum_final(struct shash_desc *desc, u8 *out) +{ + u16 *crcp = shash_desc_ctx(desc); + + *(u16 *)out = *crcp; + return 0; +} + +static struct shash_alg alg = { + .init = crct10dif_vpmsum_init, + .update = crct10dif_vpmsum_update, + .final = crct10dif_vpmsum_final, + .descsize = CRC_T10DIF_DIGEST_SIZE, + .digestsize = CRC_T10DIF_DIGEST_SIZE, + .base = { + .cra_name = "crct10dif", + .cra_driver_name = "crct10dif-vpmsum", + .cra_priority = 200, + .cra_blocksize = CRC_T10DIF_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + +static int __init crct10dif_vpmsum_mod_init(void) +{ + if (!cpu_has_feature(CPU_FTR_ARCH_207S)) + return -ENODEV; + + return crypto_register_shash(&alg); +} + +static void __exit crct10dif_vpmsum_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + +module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, crct10dif_vpmsum_mod_init); +module_exit(crct10dif_vpmsum_mod_fini); + +MODULE_AUTHOR("Daniel Axtens <dja@axtens.net>"); +MODULE_DESCRIPTION("CRCT10DIF using vector polynomial multiply-sum instructions"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CRYPTO("crct10dif"); +MODULE_ALIAS_CRYPTO("crct10dif-vpmsum"); diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index 73eb794d6163..bc5fdfd22788 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -51,6 +51,10 @@ #define PPC_BIT(bit) (1UL << PPC_BITLSHIFT(bit)) #define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs)) +/* Put a PPC bit into a "normal" bit position */ +#define PPC_BITEXTRACT(bits, ppc_bit, dst_bit) \ + ((((bits) >> PPC_BITLSHIFT(ppc_bit)) & 1) << (dst_bit)) + #include <asm/barrier.h> /* Macro for generating the ***_bits() functions */ diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 012223638815..26ed228d4dc6 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -1,6 +1,7 @@ #ifndef _ASM_POWERPC_BOOK3S_32_PGTABLE_H #define _ASM_POWERPC_BOOK3S_32_PGTABLE_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #include <asm/book3s/32/hash.h> diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 1eeeb72c7015..8f4d41936e5a 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -1,9 +1,12 @@ #ifndef _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ #define _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ +#include <asm-generic/5level-fixup.h> + #ifndef __ASSEMBLY__ #include <linux/mmdebug.h> #endif + /* * Common bits between hash and Radix page table */ @@ -347,23 +350,58 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, __r; \ }) +static inline int __pte_write(pte_t pte) +{ + return !!(pte_raw(pte) & cpu_to_be64(_PAGE_WRITE)); +} + +#ifdef CONFIG_NUMA_BALANCING +#define pte_savedwrite pte_savedwrite +static inline bool pte_savedwrite(pte_t pte) +{ + /* + * Saved write ptes are prot none ptes that doesn't have + * privileged bit sit. We mark prot none as one which has + * present and pviliged bit set and RWX cleared. To mark + * protnone which used to have _PAGE_WRITE set we clear + * the privileged bit. + */ + return !(pte_raw(pte) & cpu_to_be64(_PAGE_RWX | _PAGE_PRIVILEGED)); +} +#else +#define pte_savedwrite pte_savedwrite +static inline bool pte_savedwrite(pte_t pte) +{ + return false; +} +#endif + +static inline int pte_write(pte_t pte) +{ + return __pte_write(pte) || pte_savedwrite(pte); +} + #define __HAVE_ARCH_PTEP_SET_WRPROTECT static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - if ((pte_raw(*ptep) & cpu_to_be64(_PAGE_WRITE)) == 0) - return; - - pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0); + if (__pte_write(*ptep)) + pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0); + else if (unlikely(pte_savedwrite(*ptep))) + pte_update(mm, addr, ptep, 0, _PAGE_PRIVILEGED, 0); } static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - if ((pte_raw(*ptep) & cpu_to_be64(_PAGE_WRITE)) == 0) - return; - - pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1); + /* + * We should not find protnone for hugetlb, but this complete the + * interface. + */ + if (__pte_write(*ptep)) + pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1); + else if (unlikely(pte_savedwrite(*ptep))) + pte_update(mm, addr, ptep, 0, _PAGE_PRIVILEGED, 1); } #define __HAVE_ARCH_PTEP_GET_AND_CLEAR @@ -397,11 +435,6 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_update(mm, addr, ptep, ~0UL, 0, 0); } -static inline int pte_write(pte_t pte) -{ - return !!(pte_raw(pte) & cpu_to_be64(_PAGE_WRITE)); -} - static inline int pte_dirty(pte_t pte) { return !!(pte_raw(pte) & cpu_to_be64(_PAGE_DIRTY)); @@ -465,19 +498,12 @@ static inline pte_t pte_clear_savedwrite(pte_t pte) VM_BUG_ON(!pte_protnone(pte)); return __pte(pte_val(pte) | _PAGE_PRIVILEGED); } - -#define pte_savedwrite pte_savedwrite -static inline bool pte_savedwrite(pte_t pte) +#else +#define pte_clear_savedwrite pte_clear_savedwrite +static inline pte_t pte_clear_savedwrite(pte_t pte) { - /* - * Saved write ptes are prot none ptes that doesn't have - * privileged bit sit. We mark prot none as one which has - * present and pviliged bit set and RWX cleared. To mark - * protnone which used to have _PAGE_WRITE set we clear - * the privileged bit. - */ - VM_BUG_ON(!pte_protnone(pte)); - return !(pte_raw(pte) & cpu_to_be64(_PAGE_RWX | _PAGE_PRIVILEGED)); + VM_WARN_ON(1); + return __pte(pte_val(pte) & ~_PAGE_WRITE); } #endif /* CONFIG_NUMA_BALANCING */ @@ -506,6 +532,8 @@ static inline unsigned long pte_pfn(pte_t pte) /* Generic modifiers for PTE bits */ static inline pte_t pte_wrprotect(pte_t pte) { + if (unlikely(pte_savedwrite(pte))) + return pte_clear_savedwrite(pte); return __pte(pte_val(pte) & ~_PAGE_WRITE); } @@ -926,6 +954,7 @@ static inline int pmd_protnone(pmd_t pmd) #define __HAVE_ARCH_PMD_WRITE #define pmd_write(pmd) pte_write(pmd_pte(pmd)) +#define __pmd_write(pmd) __pte_write(pmd_pte(pmd)) #define pmd_savedwrite(pmd) pte_savedwrite(pmd_pte(pmd)) #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -982,11 +1011,10 @@ static inline int __pmdp_test_and_clear_young(struct mm_struct *mm, static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) { - - if ((pmd_raw(*pmdp) & cpu_to_be64(_PAGE_WRITE)) == 0) - return; - - pmd_hugepage_update(mm, addr, pmdp, _PAGE_WRITE, 0); + if (__pmd_write((*pmdp))) + pmd_hugepage_update(mm, addr, pmdp, _PAGE_WRITE, 0); + else if (unlikely(pmd_savedwrite(*pmdp))) + pmd_hugepage_update(mm, addr, pmdp, 0, _PAGE_PRIVILEGED); } static inline int pmd_trans_huge(pmd_t pmd) diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 3a39283333c3..f2c562a0a427 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -85,12 +85,12 @@ } \ } while (0) -#define __WARN_TAINT(taint) do { \ +#define __WARN_FLAGS(flags) do { \ __asm__ __volatile__( \ "1: twi 31,0,0\n" \ _EMIT_BUG_ENTRY \ : : "i" (__FILE__), "i" (__LINE__), \ - "i" (BUGFLAG_TAINT(taint)), \ + "i" (BUGFLAG_WARNING|(flags)), \ "i" (sizeof(struct bug_entry))); \ } while (0) diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index 4e63787dc3be..842124b199b5 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h @@ -112,7 +112,7 @@ static inline __wsum csum_add(__wsum csum, __wsum addend) #ifdef __powerpc64__ res += (__force u64)addend; - return (__force __wsum)((u32)res + (res >> 32)); + return (__force __wsum) from64to32(res); #else asm("addc %0,%0,%1;" "addze %0,%0;" diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/asm/cpuidle.h index fd321eb423cb..155731557c9b 100644 --- a/arch/powerpc/include/asm/cpuidle.h +++ b/arch/powerpc/include/asm/cpuidle.h @@ -70,8 +70,8 @@ static inline void report_invalid_psscr_val(u64 psscr_val, int err) std r0,0(r1); \ ptesync; \ ld r0,0(r1); \ -1: cmpd cr0,r0,r0; \ - bne 1b; \ +236: cmpd cr0,r0,r0; \ + bne 236b; \ IDLE_INST; \ #define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST) \ diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 93b9b84568e8..09bde6e34f5d 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -144,8 +144,8 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, #define ARCH_DLINFO_CACHE_GEOMETRY \ NEW_AUX_ENT(AT_L1I_CACHESIZE, ppc64_caches.l1i.size); \ NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, get_cache_geometry(l1i)); \ - NEW_AUX_ENT(AT_L1D_CACHESIZE, ppc64_caches.l1i.size); \ - NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, get_cache_geometry(l1i)); \ + NEW_AUX_ENT(AT_L1D_CACHESIZE, ppc64_caches.l1d.size); \ + NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, get_cache_geometry(l1d)); \ NEW_AUX_ENT(AT_L2_CACHESIZE, ppc64_caches.l2.size); \ NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, get_cache_geometry(l2)); \ NEW_AUX_ENT(AT_L3_CACHESIZE, ppc64_caches.l3.size); \ diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 14752eee3d0c..ed3beadd2cc5 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -236,9 +236,9 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) mtctr reg; \ bctr -#define BRANCH_LINK_TO_FAR(reg, label) \ - __LOAD_FAR_HANDLER(reg, label); \ - mtctr reg; \ +#define BRANCH_LINK_TO_FAR(label) \ + __LOAD_FAR_HANDLER(r12, label); \ + mtctr r12; \ bctrl /* @@ -265,7 +265,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) #define BRANCH_TO_COMMON(reg, label) \ b label -#define BRANCH_LINK_TO_FAR(reg, label) \ +#define BRANCH_LINK_TO_FAR(label) \ bl label #define BRANCH_TO_KVM(reg, label) \ diff --git a/arch/powerpc/include/asm/extable.h b/arch/powerpc/include/asm/extable.h new file mode 100644 index 000000000000..07cc45cd86d9 --- /dev/null +++ b/arch/powerpc/include/asm/extable.h @@ -0,0 +1,29 @@ +#ifndef _ARCH_POWERPC_EXTABLE_H +#define _ARCH_POWERPC_EXTABLE_H + +/* + * The exception table consists of pairs of relative 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. + */ + +#define ARCH_HAS_RELATIVE_EXTABLE + +struct exception_table_entry { + int insn; + int fixup; +}; + +static inline unsigned long extable_fixup(const struct exception_table_entry *x) +{ + return (unsigned long)&x->fixup + x->fixup; +} + +#endif diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index f97d8cb6bdf6..ed62efe01e49 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -66,6 +66,55 @@ #define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \ P8_DSISR_MC_ERAT_MULTIHIT_SEC) + +/* + * Machine Check bits on power9 + */ +#define P9_SRR1_MC_LOADSTORE(srr1) (((srr1) >> PPC_BITLSHIFT(42)) & 1) + +#define P9_SRR1_MC_IFETCH(srr1) ( \ + PPC_BITEXTRACT(srr1, 45, 0) | \ + PPC_BITEXTRACT(srr1, 44, 1) | \ + PPC_BITEXTRACT(srr1, 43, 2) | \ + PPC_BITEXTRACT(srr1, 36, 3) ) + +/* 0 is reserved */ +#define P9_SRR1_MC_IFETCH_UE 1 +#define P9_SRR1_MC_IFETCH_SLB_PARITY 2 +#define P9_SRR1_MC_IFETCH_SLB_MULTIHIT 3 +#define P9_SRR1_MC_IFETCH_ERAT_MULTIHIT 4 +#define P9_SRR1_MC_IFETCH_TLB_MULTIHIT 5 +#define P9_SRR1_MC_IFETCH_UE_TLB_RELOAD 6 +/* 7 is reserved */ +#define P9_SRR1_MC_IFETCH_LINK_TIMEOUT 8 +#define P9_SRR1_MC_IFETCH_LINK_TABLEWALK_TIMEOUT 9 +/* 10 ? */ +#define P9_SRR1_MC_IFETCH_RA 11 +#define P9_SRR1_MC_IFETCH_RA_TABLEWALK 12 +#define P9_SRR1_MC_IFETCH_RA_ASYNC_STORE 13 +#define P9_SRR1_MC_IFETCH_LINK_ASYNC_STORE_TIMEOUT 14 +#define P9_SRR1_MC_IFETCH_RA_TABLEWALK_FOREIGN 15 + +/* DSISR bits for machine check (On Power9) */ +#define P9_DSISR_MC_UE (PPC_BIT(48)) +#define P9_DSISR_MC_UE_TABLEWALK (PPC_BIT(49)) +#define P9_DSISR_MC_LINK_LOAD_TIMEOUT (PPC_BIT(50)) +#define P9_DSISR_MC_LINK_TABLEWALK_TIMEOUT (PPC_BIT(51)) +#define P9_DSISR_MC_ERAT_MULTIHIT (PPC_BIT(52)) +#define P9_DSISR_MC_TLB_MULTIHIT_MFTLB (PPC_BIT(53)) +#define P9_DSISR_MC_USER_TLBIE (PPC_BIT(54)) +#define P9_DSISR_MC_SLB_PARITY_MFSLB (PPC_BIT(55)) +#define P9_DSISR_MC_SLB_MULTIHIT_MFSLB (PPC_BIT(56)) +#define P9_DSISR_MC_RA_LOAD (PPC_BIT(57)) +#define P9_DSISR_MC_RA_TABLEWALK (PPC_BIT(58)) +#define P9_DSISR_MC_RA_TABLEWALK_FOREIGN (PPC_BIT(59)) +#define P9_DSISR_MC_RA_FOREIGN (PPC_BIT(60)) + +/* SLB error bits */ +#define P9_DSISR_MC_SLB_ERRORS (P9_DSISR_MC_ERAT_MULTIHIT | \ + P9_DSISR_MC_SLB_PARITY_MFSLB | \ + P9_DSISR_MC_SLB_MULTIHIT_MFSLB) + enum MCE_Version { MCE_V1 = 1, }; @@ -93,6 +142,9 @@ enum MCE_ErrorType { MCE_ERROR_TYPE_SLB = 2, MCE_ERROR_TYPE_ERAT = 3, MCE_ERROR_TYPE_TLB = 4, + MCE_ERROR_TYPE_USER = 5, + MCE_ERROR_TYPE_RA = 6, + MCE_ERROR_TYPE_LINK = 7, }; enum MCE_UeErrorType { @@ -121,6 +173,32 @@ enum MCE_TlbErrorType { MCE_TLB_ERROR_MULTIHIT = 2, }; +enum MCE_UserErrorType { + MCE_USER_ERROR_INDETERMINATE = 0, + MCE_USER_ERROR_TLBIE = 1, +}; + +enum MCE_RaErrorType { + MCE_RA_ERROR_INDETERMINATE = 0, + MCE_RA_ERROR_IFETCH = 1, + MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH = 2, + MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN = 3, + MCE_RA_ERROR_LOAD = 4, + MCE_RA_ERROR_STORE = 5, + MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 6, + MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN = 7, + MCE_RA_ERROR_LOAD_STORE_FOREIGN = 8, +}; + +enum MCE_LinkErrorType { + MCE_LINK_ERROR_INDETERMINATE = 0, + MCE_LINK_ERROR_IFETCH_TIMEOUT = 1, + MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT = 2, + MCE_LINK_ERROR_LOAD_TIMEOUT = 3, + MCE_LINK_ERROR_STORE_TIMEOUT = 4, + MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT = 5, +}; + struct machine_check_event { enum MCE_Version version:8; /* 0x00 */ uint8_t in_use; /* 0x01 */ @@ -166,6 +244,30 @@ struct machine_check_event { uint64_t effective_address; uint8_t reserved_2[16]; } tlb_error; + + struct { + enum MCE_UserErrorType user_error_type:8; + uint8_t effective_address_provided; + uint8_t reserved_1[6]; + uint64_t effective_address; + uint8_t reserved_2[16]; + } user_error; + + struct { + enum MCE_RaErrorType ra_error_type:8; + uint8_t effective_address_provided; + uint8_t reserved_1[6]; + uint64_t effective_address; + uint8_t reserved_2[16]; + } ra_error; + + struct { + enum MCE_LinkErrorType link_error_type:8; + uint8_t effective_address_provided; + uint8_t reserved_1[6]; + uint64_t effective_address; + uint8_t reserved_2[16]; + } link_error; } u; }; @@ -176,8 +278,12 @@ struct mce_error_info { enum MCE_SlbErrorType slb_error_type:8; enum MCE_EratErrorType erat_error_type:8; enum MCE_TlbErrorType tlb_error_type:8; + enum MCE_UserErrorType user_error_type:8; + enum MCE_RaErrorType ra_error_type:8; + enum MCE_LinkErrorType link_error_type:8; } u; - uint8_t reserved[2]; + enum MCE_Severity severity:8; + enum MCE_Initiator initiator:8; }; #define MAX_MC_EVT 100 diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b9e3f0aca261..ecf9885ab660 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -163,11 +163,5 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, /* by default, allow everything */ return true; } - -static inline bool arch_pte_access_permitted(pte_t pte, bool write) -{ - /* by default, allow everything */ - return true; -} #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_MMU_CONTEXT_H */ diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index ba9921bf202e..5134ade2e850 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h @@ -1,6 +1,7 @@ #ifndef _ASM_POWERPC_NOHASH_32_PGTABLE_H #define _ASM_POWERPC_NOHASH_32_PGTABLE_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #ifndef __ASSEMBLY__ diff --git a/arch/powerpc/include/asm/nohash/64/pgtable-4k.h b/arch/powerpc/include/asm/nohash/64/pgtable-4k.h index d0db98793dd8..9f4de0a1035e 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable-4k.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable-4k.h @@ -1,5 +1,8 @@ #ifndef _ASM_POWERPC_NOHASH_64_PGTABLE_4K_H #define _ASM_POWERPC_NOHASH_64_PGTABLE_4K_H + +#include <asm-generic/5level-fixup.h> + /* * Entries per page directory level. The PTE level must use a 64b record * for each page table entry. The PMD and PGD level use a 32b record for diff --git a/arch/powerpc/include/asm/nohash/64/pgtable-64k.h b/arch/powerpc/include/asm/nohash/64/pgtable-64k.h index 55b28ef3409a..1facb584dd29 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable-64k.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable-64k.h @@ -1,6 +1,7 @@ #ifndef _ASM_POWERPC_NOHASH_64_PGTABLE_64K_H #define _ASM_POWERPC_NOHASH_64_PGTABLE_64K_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index 0cd8a3852763..e5805ad78e12 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h @@ -230,7 +230,7 @@ static inline int hugepd_ok(hugepd_t hpd) return ((hpd_val(hpd) & 0x4) != 0); #else /* We clear the top bit to indicate hugepd */ - return ((hpd_val(hpd) & PD_HUGE) == 0); + return (hpd_val(hpd) && (hpd_val(hpd) & PD_HUGE) == 0); #endif } diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index d99bd442aacb..e7d6d86563ee 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -284,6 +284,13 @@ #define PPC_INST_BRANCH_COND 0x40800000 #define PPC_INST_LBZCIX 0x7c0006aa #define PPC_INST_STBCIX 0x7c0007aa +#define PPC_INST_LWZX 0x7c00002e +#define PPC_INST_LFSX 0x7c00042e +#define PPC_INST_STFSX 0x7c00052e +#define PPC_INST_LFDX 0x7c0004ae +#define PPC_INST_STFDX 0x7c0005ae +#define PPC_INST_LVX 0x7c0000ce +#define PPC_INST_STVX 0x7c0001ce /* macros to insert fields into opcodes */ #define ___PPC_RA(a) (((a) & 0x1f) << 16) diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index 4a90634e8322..35c00d7a0cf8 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h @@ -160,12 +160,18 @@ struct of_drconf_cell { #define OV5_PFO_HW_ENCR 0x1120 /* PFO Encryption Accelerator */ #define OV5_SUB_PROCESSORS 0x1501 /* 1,2,or 4 Sub-Processors supported */ #define OV5_XIVE_EXPLOIT 0x1701 /* XIVE exploitation supported */ -#define OV5_MMU_RADIX_300 0x1880 /* ISA v3.00 radix MMU supported */ -#define OV5_MMU_HASH_300 0x1840 /* ISA v3.00 hash MMU supported */ -#define OV5_MMU_SEGM_RADIX 0x1820 /* radix mode (no segmentation) */ -#define OV5_MMU_PROC_TBL 0x1810 /* hcall selects SLB or proc table */ -#define OV5_MMU_SLB 0x1800 /* always use SLB */ -#define OV5_MMU_GTSE 0x1808 /* Guest translation shootdown */ +/* MMU Base Architecture */ +#define OV5_MMU_SUPPORT 0x18C0 /* MMU Mode Support Mask */ +#define OV5_MMU_HASH 0x1800 /* Hash MMU Only */ +#define OV5_MMU_RADIX 0x1840 /* Radix MMU Only */ +#define OV5_MMU_EITHER 0x1880 /* Hash or Radix Supported */ +#define OV5_MMU_DYNAMIC 0x18C0 /* Hash or Radix Can Switch Later */ +#define OV5_NMMU 0x1820 /* Nest MMU Available */ +/* Hash Table Extensions */ +#define OV5_HASH_SEG_TBL 0x1980 /* In Memory Segment Tables Available */ +#define OV5_HASH_GTSE 0x1940 /* Guest Translation Shoot Down Avail */ +/* Radix Table Extensions */ +#define OV5_RADIX_GTSE 0x1A40 /* Guest Translation Shoot Down Avail */ /* Option Vector 6: IBM PAPR hints */ #define OV6_LINUX 0x02 /* Linux is our OS */ diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 4b369d83fe9c..1c9470881c4a 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -387,3 +387,4 @@ SYSCALL(copy_file_range) COMPAT_SYS_SPU(preadv2) COMPAT_SYS_SPU(pwritev2) SYSCALL(kexec_file_load) +SYSCALL(statx) diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 0e6add3187bc..5c0d8a8cdae5 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -1,18 +1,11 @@ #ifndef _ARCH_POWERPC_UACCESS_H #define _ARCH_POWERPC_UACCESS_H -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ - -#include <linux/sched.h> -#include <linux/errno.h> #include <asm/asm-compat.h> #include <asm/ppc_asm.h> #include <asm/processor.h> #include <asm/page.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 +#include <asm/extable.h> /* * The fs value determines whether argument validity checking should be @@ -64,31 +57,6 @@ __access_ok((__force unsigned long)(addr), (size), get_fs())) /* - * The exception table consists of pairs of relative 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. - */ - -#define ARCH_HAS_RELATIVE_EXTABLE - -struct exception_table_entry { - int insn; - int fixup; -}; - -static inline unsigned long extable_fixup(const struct exception_table_entry *x) -{ - return (unsigned long)&x->fixup + x->fixup; -} - -/* * These are the main single-value transfer routines. They automatically * use the right size if we just have the right pointer type. * @@ -301,42 +269,19 @@ extern unsigned long __copy_tofrom_user(void __user *to, #ifndef __powerpc64__ -static inline unsigned long copy_from_user(void *to, - const void __user *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_READ, from, n))) { - check_object_size(to, n, false); - return __copy_tofrom_user((__force void __user *)to, from, n); - } - memset(to, 0, n); - return n; -} - -static inline unsigned long copy_to_user(void __user *to, - const void *from, unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) { - check_object_size(from, n, true); - return __copy_tofrom_user(to, (__force void __user *)from, n); - } - return n; -} +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER #else /* __powerpc64__ */ -#define __copy_in_user(to, from, size) \ - __copy_tofrom_user((to), (from), (size)) - -extern unsigned long copy_from_user(void *to, const void __user *from, - unsigned long n); -extern unsigned long copy_to_user(void __user *to, const void *from, - unsigned long n); -extern unsigned long copy_in_user(void __user *to, const void __user *from, - unsigned long n); - +static inline unsigned long +raw_copy_in_user(void __user *to, const void __user *from, unsigned long n) +{ + return __copy_tofrom_user(to, from, n); +} #endif /* __powerpc64__ */ -static inline unsigned long __copy_from_user_inatomic(void *to, +static inline unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { @@ -360,12 +305,10 @@ static inline unsigned long __copy_from_user_inatomic(void *to, return 0; } - check_object_size(to, n, false); - return __copy_tofrom_user((__force void __user *)to, from, n); } -static inline unsigned long __copy_to_user_inatomic(void __user *to, +static inline unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { @@ -389,25 +332,9 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to, return 0; } - check_object_size(from, n, true); - return __copy_tofrom_user(to, (__force const void __user *)from, n); } -static inline unsigned long __copy_from_user(void *to, - const void __user *from, unsigned long size) -{ - might_fault(); - return __copy_from_user_inatomic(to, from, size); -} - -static inline unsigned long __copy_to_user(void __user *to, - const void *from, unsigned long size) -{ - might_fault(); - return __copy_to_user_inatomic(to, from, size); -} - extern unsigned long __clear_user(void __user *addr, unsigned long size); static inline unsigned long clear_user(void __user *addr, unsigned long size) @@ -422,7 +349,4 @@ extern long strncpy_from_user(char *dst, 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); -#endif /* __ASSEMBLY__ */ -#endif /* __KERNEL__ */ - #endif /* _ARCH_POWERPC_UACCESS_H */ diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index eb1acee91a20..9ba11dbcaca9 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -12,7 +12,7 @@ #include <uapi/asm/unistd.h> -#define NR_syscalls 383 +#define NR_syscalls 384 #define __NR__exit __NR_exit diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h index 44583a52f882..58e2ec0310fc 100644 --- a/arch/powerpc/include/uapi/asm/socket.h +++ b/arch/powerpc/include/uapi/asm/socket.h @@ -99,4 +99,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index 2f26335a3c42..b85f14228857 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h @@ -393,5 +393,6 @@ #define __NR_preadv2 380 #define __NR_pwritev2 381 #define __NR_kexec_file_load 382 +#define __NR_statx 383 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index cbc7c42cdb74..ec7a8b099dd9 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -807,14 +807,25 @@ int fix_alignment(struct pt_regs *regs) nb = aligninfo[instr].len; flags = aligninfo[instr].flags; - /* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */ - if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) { - nb = 8; - flags = LD+SW; - } else if (IS_XFORM(instruction) && - ((instruction >> 1) & 0x3ff) == 660) { - nb = 8; - flags = ST+SW; + /* + * Handle some cases which give overlaps in the DSISR values. + */ + if (IS_XFORM(instruction)) { + switch (get_xop(instruction)) { + case 532: /* ldbrx */ + nb = 8; + flags = LD+SW; + break; + case 660: /* stdbrx */ + nb = 8; + flags = ST+SW; + break; + case 20: /* lwarx */ + case 84: /* ldarx */ + case 116: /* lharx */ + case 276: /* lqarx */ + return 0; /* not emulated ever */ + } } /* Byteswap little endian loads and stores */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index bb7a1890aeb7..e79b9daa873c 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -77,6 +77,7 @@ extern void __flush_tlb_power8(unsigned int action); extern void __flush_tlb_power9(unsigned int action); extern long __machine_check_early_realmode_p7(struct pt_regs *regs); extern long __machine_check_early_realmode_p8(struct pt_regs *regs); +extern long __machine_check_early_realmode_p9(struct pt_regs *regs); #endif /* CONFIG_PPC64 */ #if defined(CONFIG_E500) extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec); @@ -540,6 +541,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_setup = __setup_cpu_power9, .cpu_restore = __restore_cpu_power9, .flush_tlb = __flush_tlb_power9, + .machine_check_early = __machine_check_early_realmode_p9, .platform = "power9", }, { /* Power9 */ @@ -559,6 +561,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_setup = __setup_cpu_power9, .cpu_restore = __restore_cpu_power9, .flush_tlb = __flush_tlb_power9, + .machine_check_early = __machine_check_early_realmode_p9, .platform = "power9", }, { /* Cell Broadband Engine */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 6432d4bf08c8..767ef6d68c9e 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -689,7 +689,7 @@ resume_kernel: addi r8,r1,INT_FRAME_SIZE /* Get the kprobed function entry */ - lwz r3,GPR1(r1) + ld r3,GPR1(r1) subi r3,r3,INT_FRAME_SIZE /* dst: Allocate a trampoline exception frame */ mr r4,r1 /* src: current exception frame */ mr r1,r3 /* Reroute the trampoline frame to r1 */ @@ -703,8 +703,8 @@ resume_kernel: addi r6,r6,8 bdnz 2b - /* Do real store operation to complete stwu */ - lwz r5,GPR1(r1) + /* Do real store operation to complete stdu */ + ld r5,GPR1(r1) std r8,0(r5) /* Clear _TIF_EMULATE_STACK_STORE flag */ diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 857bf7c5b946..6353019966e6 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -982,7 +982,7 @@ TRAMP_REAL_BEGIN(hmi_exception_early) EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN) EXCEPTION_PROLOG_COMMON_3(0xe60) addi r3,r1,STACK_FRAME_OVERHEAD - BRANCH_LINK_TO_FAR(r4, hmi_exception_realmode) + BRANCH_LINK_TO_FAR(hmi_exception_realmode) /* Function call ABI */ /* Windup the stack. */ /* Move original HSRR0 and HSRR1 into the respective regs */ ld r9,_MSR(r1) diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S index 5f61cc0349c0..6fd08219248d 100644 --- a/arch/powerpc/kernel/idle_book3s.S +++ b/arch/powerpc/kernel/idle_book3s.S @@ -276,19 +276,21 @@ power_enter_stop: */ andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED clrldi r3,r3,60 /* r3 = Bits[60:63] = Requested Level (RL) */ - bne 1f + bne .Lhandle_esl_ec_set IDLE_STATE_ENTER_SEQ(PPC_STOP) li r3,0 /* Since we didn't lose state, return 0 */ b pnv_wakeup_noloss + +.Lhandle_esl_ec_set: /* * Check if the requested state is a deep idle state. */ -1: LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state) + LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state) ld r4,ADDROFF(pnv_first_deep_stop_state)(r5) cmpd r3,r4 - bge 2f + bge .Lhandle_deep_stop IDLE_STATE_ENTER_SEQ_NORET(PPC_STOP) -2: +.Lhandle_deep_stop: /* * Entering deep idle state. * Clear thread bit in PACA_CORE_IDLE_STATE, save SPRs to @@ -447,9 +449,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) _GLOBAL(pnv_wakeup_tb_loss) ld r1,PACAR1(r13) /* - * Before entering any idle state, the NVGPRs are saved in the stack - * and they are restored before switching to the process context. Hence - * until they are restored, they are free to be used. + * Before entering any idle state, the NVGPRs are saved in the stack. + * If there was a state loss, or PACA_NAPSTATELOST was set, then the + * NVGPRs are restored. If we are here, it is likely that state is lost, + * but not guaranteed -- neither ISA207 nor ISA300 tests to reach + * here are the same as the test to restore NVGPRS: + * PACA_THREAD_IDLE_STATE test for ISA207, PSSCR test for ISA300, + * and SRR1 test for restoring NVGPRs. + * + * We are about to clobber NVGPRs now, so set NAPSTATELOST to + * guarantee they will always be restored. This might be tightened + * with careful reading of specs (particularly for ISA300) but this + * is already a slow wakeup path and it's simpler to be safe. + */ + li r0,1 + stb r0,PACA_NAPSTATELOST(r13) + + /* * * Save SRR1 and LR in NVGPRs as they might be clobbered in * opal_call() (called in CHECK_HMI_INTERRUPT). SRR1 is required diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index c6923ff45131..a1475e6aef3a 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -58,6 +58,15 @@ static void mce_set_error_info(struct machine_check_event *mce, case MCE_ERROR_TYPE_TLB: mce->u.tlb_error.tlb_error_type = mce_err->u.tlb_error_type; break; + case MCE_ERROR_TYPE_USER: + mce->u.user_error.user_error_type = mce_err->u.user_error_type; + break; + case MCE_ERROR_TYPE_RA: + mce->u.ra_error.ra_error_type = mce_err->u.ra_error_type; + break; + case MCE_ERROR_TYPE_LINK: + mce->u.link_error.link_error_type = mce_err->u.link_error_type; + break; case MCE_ERROR_TYPE_UNKNOWN: default: break; @@ -90,13 +99,14 @@ void save_mce_event(struct pt_regs *regs, long handled, mce->gpr3 = regs->gpr[3]; mce->in_use = 1; - mce->initiator = MCE_INITIATOR_CPU; /* Mark it recovered if we have handled it and MSR(RI=1). */ if (handled && (regs->msr & MSR_RI)) mce->disposition = MCE_DISPOSITION_RECOVERED; else mce->disposition = MCE_DISPOSITION_NOT_RECOVERED; - mce->severity = MCE_SEV_ERROR_SYNC; + + mce->initiator = mce_err->initiator; + mce->severity = mce_err->severity; /* * Populate the mce error_type and type-specific error_type. @@ -115,6 +125,15 @@ void save_mce_event(struct pt_regs *regs, long handled, } else if (mce->error_type == MCE_ERROR_TYPE_ERAT) { mce->u.erat_error.effective_address_provided = true; mce->u.erat_error.effective_address = addr; + } else if (mce->error_type == MCE_ERROR_TYPE_USER) { + mce->u.user_error.effective_address_provided = true; + mce->u.user_error.effective_address = addr; + } else if (mce->error_type == MCE_ERROR_TYPE_RA) { + mce->u.ra_error.effective_address_provided = true; + mce->u.ra_error.effective_address = addr; + } else if (mce->error_type == MCE_ERROR_TYPE_LINK) { + mce->u.link_error.effective_address_provided = true; + mce->u.link_error.effective_address = addr; } else if (mce->error_type == MCE_ERROR_TYPE_UE) { mce->u.ue_error.effective_address_provided = true; mce->u.ue_error.effective_address = addr; @@ -239,6 +258,29 @@ void machine_check_print_event_info(struct machine_check_event *evt) "Parity", "Multihit", }; + static const char *mc_user_types[] = { + "Indeterminate", + "tlbie(l) invalid", + }; + static const char *mc_ra_types[] = { + "Indeterminate", + "Instruction fetch (bad)", + "Page table walk ifetch (bad)", + "Page table walk ifetch (foreign)", + "Load (bad)", + "Store (bad)", + "Page table walk Load/Store (bad)", + "Page table walk Load/Store (foreign)", + "Load/Store (foreign)", + }; + static const char *mc_link_types[] = { + "Indeterminate", + "Instruction fetch (timeout)", + "Page table walk ifetch (timeout)", + "Load (timeout)", + "Store (timeout)", + "Page table walk Load/Store (timeout)", + }; /* Print things out */ if (evt->version != MCE_V1) { @@ -315,6 +357,36 @@ void machine_check_print_event_info(struct machine_check_event *evt) printk("%s Effective address: %016llx\n", level, evt->u.tlb_error.effective_address); break; + case MCE_ERROR_TYPE_USER: + subtype = evt->u.user_error.user_error_type < + ARRAY_SIZE(mc_user_types) ? + mc_user_types[evt->u.user_error.user_error_type] + : "Unknown"; + printk("%s Error type: User [%s]\n", level, subtype); + if (evt->u.user_error.effective_address_provided) + printk("%s Effective address: %016llx\n", + level, evt->u.user_error.effective_address); + break; + case MCE_ERROR_TYPE_RA: + subtype = evt->u.ra_error.ra_error_type < + ARRAY_SIZE(mc_ra_types) ? + mc_ra_types[evt->u.ra_error.ra_error_type] + : "Unknown"; + printk("%s Error type: Real address [%s]\n", level, subtype); + if (evt->u.ra_error.effective_address_provided) + printk("%s Effective address: %016llx\n", + level, evt->u.ra_error.effective_address); + break; + case MCE_ERROR_TYPE_LINK: + subtype = evt->u.link_error.link_error_type < + ARRAY_SIZE(mc_link_types) ? + mc_link_types[evt->u.link_error.link_error_type] + : "Unknown"; + printk("%s Error type: Link [%s]\n", level, subtype); + if (evt->u.link_error.effective_address_provided) + printk("%s Effective address: %016llx\n", + level, evt->u.link_error.effective_address); + break; default: case MCE_ERROR_TYPE_UNKNOWN: printk("%s Error type: Unknown\n", level); @@ -341,6 +413,18 @@ uint64_t get_mce_fault_addr(struct machine_check_event *evt) if (evt->u.tlb_error.effective_address_provided) return evt->u.tlb_error.effective_address; break; + case MCE_ERROR_TYPE_USER: + if (evt->u.user_error.effective_address_provided) + return evt->u.user_error.effective_address; + break; + case MCE_ERROR_TYPE_RA: + if (evt->u.ra_error.effective_address_provided) + return evt->u.ra_error.effective_address; + break; + case MCE_ERROR_TYPE_LINK: + if (evt->u.link_error.effective_address_provided) + return evt->u.link_error.effective_address; + break; default: case MCE_ERROR_TYPE_UNKNOWN: break; diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index 7353991c4ece..763d6f58caa8 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -116,6 +116,51 @@ static void flush_and_reload_slb(void) } #endif +static void flush_erat(void) +{ + asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); +} + +#define MCE_FLUSH_SLB 1 +#define MCE_FLUSH_TLB 2 +#define MCE_FLUSH_ERAT 3 + +static int mce_flush(int what) +{ +#ifdef CONFIG_PPC_STD_MMU_64 + if (what == MCE_FLUSH_SLB) { + flush_and_reload_slb(); + return 1; + } +#endif + if (what == MCE_FLUSH_ERAT) { + flush_erat(); + return 1; + } + if (what == MCE_FLUSH_TLB) { + if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { + cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_GLOBAL); + return 1; + } + } + + return 0; +} + +static int mce_handle_flush_derrors(uint64_t dsisr, uint64_t slb, uint64_t tlb, uint64_t erat) +{ + if ((dsisr & slb) && mce_flush(MCE_FLUSH_SLB)) + dsisr &= ~slb; + if ((dsisr & erat) && mce_flush(MCE_FLUSH_ERAT)) + dsisr &= ~erat; + if ((dsisr & tlb) && mce_flush(MCE_FLUSH_TLB)) + dsisr &= ~tlb; + /* Any other errors we don't understand? */ + if (dsisr) + return 0; + return 1; +} + static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits) { long handled = 1; @@ -281,6 +326,9 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs) long handled = 1; struct mce_error_info mce_error_info = { 0 }; + mce_error_info.severity = MCE_SEV_ERROR_SYNC; + mce_error_info.initiator = MCE_INITIATOR_CPU; + srr1 = regs->msr; nip = regs->nip; @@ -352,6 +400,9 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs) long handled = 1; struct mce_error_info mce_error_info = { 0 }; + mce_error_info.severity = MCE_SEV_ERROR_SYNC; + mce_error_info.initiator = MCE_INITIATOR_CPU; + srr1 = regs->msr; nip = regs->nip; @@ -372,3 +423,189 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs) save_mce_event(regs, handled, &mce_error_info, nip, addr); return handled; } + +static int mce_handle_derror_p9(struct pt_regs *regs) +{ + uint64_t dsisr = regs->dsisr; + + return mce_handle_flush_derrors(dsisr, + P9_DSISR_MC_SLB_PARITY_MFSLB | + P9_DSISR_MC_SLB_MULTIHIT_MFSLB, + + P9_DSISR_MC_TLB_MULTIHIT_MFTLB, + + P9_DSISR_MC_ERAT_MULTIHIT); +} + +static int mce_handle_ierror_p9(struct pt_regs *regs) +{ + uint64_t srr1 = regs->msr; + + switch (P9_SRR1_MC_IFETCH(srr1)) { + case P9_SRR1_MC_IFETCH_SLB_PARITY: + case P9_SRR1_MC_IFETCH_SLB_MULTIHIT: + return mce_flush(MCE_FLUSH_SLB); + case P9_SRR1_MC_IFETCH_TLB_MULTIHIT: + return mce_flush(MCE_FLUSH_TLB); + case P9_SRR1_MC_IFETCH_ERAT_MULTIHIT: + return mce_flush(MCE_FLUSH_ERAT); + default: + return 0; + } +} + +static void mce_get_derror_p9(struct pt_regs *regs, + struct mce_error_info *mce_err, uint64_t *addr) +{ + uint64_t dsisr = regs->dsisr; + + mce_err->severity = MCE_SEV_ERROR_SYNC; + mce_err->initiator = MCE_INITIATOR_CPU; + + if (dsisr & P9_DSISR_MC_USER_TLBIE) + *addr = regs->nip; + else + *addr = regs->dar; + + if (dsisr & P9_DSISR_MC_UE) { + mce_err->error_type = MCE_ERROR_TYPE_UE; + mce_err->u.ue_error_type = MCE_UE_ERROR_LOAD_STORE; + } else if (dsisr & P9_DSISR_MC_UE_TABLEWALK) { + mce_err->error_type = MCE_ERROR_TYPE_UE; + mce_err->u.ue_error_type = MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE; + } else if (dsisr & P9_DSISR_MC_LINK_LOAD_TIMEOUT) { + mce_err->error_type = MCE_ERROR_TYPE_LINK; + mce_err->u.link_error_type = MCE_LINK_ERROR_LOAD_TIMEOUT; + } else if (dsisr & P9_DSISR_MC_LINK_TABLEWALK_TIMEOUT) { + mce_err->error_type = MCE_ERROR_TYPE_LINK; + mce_err->u.link_error_type = MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT; + } else if (dsisr & P9_DSISR_MC_ERAT_MULTIHIT) { + mce_err->error_type = MCE_ERROR_TYPE_ERAT; + mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT; + } else if (dsisr & P9_DSISR_MC_TLB_MULTIHIT_MFTLB) { + mce_err->error_type = MCE_ERROR_TYPE_TLB; + mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT; + } else if (dsisr & P9_DSISR_MC_USER_TLBIE) { + mce_err->error_type = MCE_ERROR_TYPE_USER; + mce_err->u.user_error_type = MCE_USER_ERROR_TLBIE; + } else if (dsisr & P9_DSISR_MC_SLB_PARITY_MFSLB) { + mce_err->error_type = MCE_ERROR_TYPE_SLB; + mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY; + } else if (dsisr & P9_DSISR_MC_SLB_MULTIHIT_MFSLB) { + mce_err->error_type = MCE_ERROR_TYPE_SLB; + mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT; + } else if (dsisr & P9_DSISR_MC_RA_LOAD) { + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_LOAD; + } else if (dsisr & P9_DSISR_MC_RA_TABLEWALK) { + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE; + } else if (dsisr & P9_DSISR_MC_RA_TABLEWALK_FOREIGN) { + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN; + } else if (dsisr & P9_DSISR_MC_RA_FOREIGN) { + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_LOAD_STORE_FOREIGN; + } +} + +static void mce_get_ierror_p9(struct pt_regs *regs, + struct mce_error_info *mce_err, uint64_t *addr) +{ + uint64_t srr1 = regs->msr; + + switch (P9_SRR1_MC_IFETCH(srr1)) { + case P9_SRR1_MC_IFETCH_RA_ASYNC_STORE: + case P9_SRR1_MC_IFETCH_LINK_ASYNC_STORE_TIMEOUT: + mce_err->severity = MCE_SEV_FATAL; + break; + default: + mce_err->severity = MCE_SEV_ERROR_SYNC; + break; + } + + mce_err->initiator = MCE_INITIATOR_CPU; + + *addr = regs->nip; + + switch (P9_SRR1_MC_IFETCH(srr1)) { + case P9_SRR1_MC_IFETCH_UE: + mce_err->error_type = MCE_ERROR_TYPE_UE; + mce_err->u.ue_error_type = MCE_UE_ERROR_IFETCH; + break; + case P9_SRR1_MC_IFETCH_SLB_PARITY: + mce_err->error_type = MCE_ERROR_TYPE_SLB; + mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY; + break; + case P9_SRR1_MC_IFETCH_SLB_MULTIHIT: + mce_err->error_type = MCE_ERROR_TYPE_SLB; + mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT; + break; + case P9_SRR1_MC_IFETCH_ERAT_MULTIHIT: + mce_err->error_type = MCE_ERROR_TYPE_ERAT; + mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT; + break; + case P9_SRR1_MC_IFETCH_TLB_MULTIHIT: + mce_err->error_type = MCE_ERROR_TYPE_TLB; + mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT; + break; + case P9_SRR1_MC_IFETCH_UE_TLB_RELOAD: + mce_err->error_type = MCE_ERROR_TYPE_UE; + mce_err->u.ue_error_type = MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH; + break; + case P9_SRR1_MC_IFETCH_LINK_TIMEOUT: + mce_err->error_type = MCE_ERROR_TYPE_LINK; + mce_err->u.link_error_type = MCE_LINK_ERROR_IFETCH_TIMEOUT; + break; + case P9_SRR1_MC_IFETCH_LINK_TABLEWALK_TIMEOUT: + mce_err->error_type = MCE_ERROR_TYPE_LINK; + mce_err->u.link_error_type = MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT; + break; + case P9_SRR1_MC_IFETCH_RA: + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_IFETCH; + break; + case P9_SRR1_MC_IFETCH_RA_TABLEWALK: + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH; + break; + case P9_SRR1_MC_IFETCH_RA_ASYNC_STORE: + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_STORE; + break; + case P9_SRR1_MC_IFETCH_LINK_ASYNC_STORE_TIMEOUT: + mce_err->error_type = MCE_ERROR_TYPE_LINK; + mce_err->u.link_error_type = MCE_LINK_ERROR_STORE_TIMEOUT; + break; + case P9_SRR1_MC_IFETCH_RA_TABLEWALK_FOREIGN: + mce_err->error_type = MCE_ERROR_TYPE_RA; + mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN; + break; + default: + break; + } +} + +long __machine_check_early_realmode_p9(struct pt_regs *regs) +{ + uint64_t nip, addr; + long handled; + struct mce_error_info mce_error_info = { 0 }; + + nip = regs->nip; + + if (P9_SRR1_MC_LOADSTORE(regs->msr)) { + handled = mce_handle_derror_p9(regs); + mce_get_derror_p9(regs, &mce_error_info, &addr); + } else { + handled = mce_handle_ierror_p9(regs); + mce_get_ierror_p9(regs, &mce_error_info, &addr); + } + + /* Handle UE error. */ + if (mce_error_info.error_type == MCE_ERROR_TYPE_UE) + handled = mce_handle_ue_error(regs); + + save_mce_event(regs, handled, &mce_error_info, nip, addr); + return handled; +} diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae179cb1bb3c..c119044cad0d 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -67,7 +67,7 @@ PPC64_CACHES: * flush all bytes from start through stop-1 inclusive */ -_GLOBAL(flush_icache_range) +_GLOBAL_TOC(flush_icache_range) BEGIN_FTR_SECTION PURGE_PREFETCHED_INS blr @@ -120,7 +120,7 @@ EXPORT_SYMBOL(flush_icache_range) * * flush all bytes from start to stop-1 inclusive */ -_GLOBAL(flush_dcache_range) +_GLOBAL_TOC(flush_dcache_range) /* * Flush the data cache to memory diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index d5e2b8309939..eae61b044e9e 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -389,51 +389,40 @@ static int nvram_pstore_open(struct pstore_info *psi) /** * nvram_pstore_write - pstore write callback for nvram - * @type: Type of message logged - * @reason: reason behind dump (oops/panic) - * @id: identifier to indicate the write performed - * @part: pstore writes data to registered buffer in parts, - * part number will indicate the same. - * @count: Indicates oops count - * @compressed: Flag to indicate the log is compressed - * @size: number of bytes written to the registered buffer - * @psi: registered pstore_info structure + * @record: pstore record to write, with @id to be set * * Called by pstore_dump() when an oops or panic report is logged in the * printk buffer. * Returns 0 on successful write. */ -static int nvram_pstore_write(enum pstore_type_id type, - enum kmsg_dump_reason reason, - u64 *id, unsigned int part, int count, - bool compressed, size_t size, - struct pstore_info *psi) +static int nvram_pstore_write(struct pstore_record *record) { int rc; unsigned int err_type = ERR_TYPE_KERNEL_PANIC; struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf; /* part 1 has the recent messages from printk buffer */ - if (part > 1 || (type != PSTORE_TYPE_DMESG)) + if (record->part > 1 || (record->type != PSTORE_TYPE_DMESG)) return -1; if (clobbering_unread_rtas_event()) return -1; oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); - oops_hdr->report_length = cpu_to_be16(size); + oops_hdr->report_length = cpu_to_be16(record->size); oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds()); - if (compressed) + if (record->compressed) err_type = ERR_TYPE_KERNEL_PANIC_GZ; rc = nvram_write_os_partition(&oops_log_partition, oops_buf, - (int) (sizeof(*oops_hdr) + size), err_type, count); + (int) (sizeof(*oops_hdr) + record->size), err_type, + record->count); if (rc != 0) return rc; - *id = part; + record->id = record->part; return 0; } @@ -442,10 +431,7 @@ static int nvram_pstore_write(enum pstore_type_id type, * Returns the length of the data we read from each partition. * Returns 0 if we've been called before. */ -static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, - int *count, struct timespec *time, char **buf, - bool *compressed, ssize_t *ecc_notice_size, - struct pstore_info *psi) +static ssize_t nvram_pstore_read(struct pstore_record *record) { struct oops_log_info *oops_hdr; unsigned int err_type, id_no, size = 0; @@ -459,40 +445,40 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, switch (nvram_type_ids[read_type]) { case PSTORE_TYPE_DMESG: part = &oops_log_partition; - *type = PSTORE_TYPE_DMESG; + record->type = PSTORE_TYPE_DMESG; break; case PSTORE_TYPE_PPC_COMMON: sig = NVRAM_SIG_SYS; part = &common_partition; - *type = PSTORE_TYPE_PPC_COMMON; - *id = PSTORE_TYPE_PPC_COMMON; - time->tv_sec = 0; - time->tv_nsec = 0; + record->type = PSTORE_TYPE_PPC_COMMON; + record->id = PSTORE_TYPE_PPC_COMMON; + record->time.tv_sec = 0; + record->time.tv_nsec = 0; break; #ifdef CONFIG_PPC_PSERIES case PSTORE_TYPE_PPC_RTAS: part = &rtas_log_partition; - *type = PSTORE_TYPE_PPC_RTAS; - time->tv_sec = last_rtas_event; - time->tv_nsec = 0; + record->type = PSTORE_TYPE_PPC_RTAS; + record->time.tv_sec = last_rtas_event; + record->time.tv_nsec = 0; break; case PSTORE_TYPE_PPC_OF: sig = NVRAM_SIG_OF; part = &of_config_partition; - *type = PSTORE_TYPE_PPC_OF; - *id = PSTORE_TYPE_PPC_OF; - time->tv_sec = 0; - time->tv_nsec = 0; + record->type = PSTORE_TYPE_PPC_OF; + record->id = PSTORE_TYPE_PPC_OF; + record->time.tv_sec = 0; + record->time.tv_nsec = 0; break; #endif #ifdef CONFIG_PPC_POWERNV case PSTORE_TYPE_PPC_OPAL: sig = NVRAM_SIG_FW; part = &skiboot_partition; - *type = PSTORE_TYPE_PPC_OPAL; - *id = PSTORE_TYPE_PPC_OPAL; - time->tv_sec = 0; - time->tv_nsec = 0; + record->type = PSTORE_TYPE_PPC_OPAL; + record->id = PSTORE_TYPE_PPC_OPAL; + record->time.tv_sec = 0; + record->time.tv_nsec = 0; break; #endif default: @@ -520,10 +506,10 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, return 0; } - *count = 0; + record->count = 0; if (part->os_partition) - *id = id_no; + record->id = id_no; if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { size_t length, hdr_size; @@ -533,34 +519,35 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, /* Old format oops header had 2-byte record size */ hdr_size = sizeof(u16); length = be16_to_cpu(oops_hdr->version); - time->tv_sec = 0; - time->tv_nsec = 0; + record->time.tv_sec = 0; + record->time.tv_nsec = 0; } else { hdr_size = sizeof(*oops_hdr); length = be16_to_cpu(oops_hdr->report_length); - time->tv_sec = be64_to_cpu(oops_hdr->timestamp); - time->tv_nsec = 0; + record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp); + record->time.tv_nsec = 0; } - *buf = kmemdup(buff + hdr_size, length, GFP_KERNEL); + record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL); kfree(buff); - if (*buf == NULL) + if (record->buf == NULL) return -ENOMEM; - *ecc_notice_size = 0; + record->ecc_notice_size = 0; if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) - *compressed = true; + record->compressed = true; else - *compressed = false; + record->compressed = false; return length; } - *buf = buff; + record->buf = buff; return part->size; } static struct pstore_info nvram_pstore_info = { .owner = THIS_MODULE, .name = "nvram", + .flags = PSTORE_FLAGS_DMESG, .open = nvram_pstore_open, .read = nvram_pstore_read, .write = nvram_pstore_write, diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index a3944540fe0d..1c1b44ec7642 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -168,6 +168,14 @@ static unsigned long __initdata prom_tce_alloc_start; static unsigned long __initdata prom_tce_alloc_end; #endif +static bool __initdata prom_radix_disable; + +struct platform_support { + bool hash_mmu; + bool radix_mmu; + bool radix_gtse; +}; + /* Platforms codes are now obsolete in the kernel. Now only used within this * file and ultimately gone too. Feel free to change them if you need, they * are not shared with anything outside of this file anymore @@ -626,6 +634,12 @@ static void __init early_cmdline_parse(void) prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000); #endif } + + opt = strstr(prom_cmd_line, "disable_radix"); + if (opt) { + prom_debug("Radix disabled from cmdline\n"); + prom_radix_disable = true; + } } #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) @@ -695,6 +709,8 @@ struct option_vector5 { u8 byte22; u8 intarch; u8 mmu; + u8 hash_ext; + u8 radix_ext; } __packed; struct option_vector6 { @@ -850,8 +866,9 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { .reserved3 = 0, .subprocessors = 1, .intarch = 0, - .mmu = OV5_FEAT(OV5_MMU_RADIX_300) | OV5_FEAT(OV5_MMU_HASH_300) | - OV5_FEAT(OV5_MMU_PROC_TBL) | OV5_FEAT(OV5_MMU_GTSE), + .mmu = 0, + .hash_ext = 0, + .radix_ext = 0, }, /* option vector 6: IBM PAPR hints */ @@ -990,6 +1007,92 @@ static int __init prom_count_smt_threads(void) } +static void __init prom_parse_mmu_model(u8 val, + struct platform_support *support) +{ + switch (val) { + case OV5_FEAT(OV5_MMU_DYNAMIC): + case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */ + prom_debug("MMU - either supported\n"); + support->radix_mmu = !prom_radix_disable; + support->hash_mmu = true; + break; + case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */ + prom_debug("MMU - radix only\n"); + if (prom_radix_disable) { + /* + * If we __have__ to do radix, we're better off ignoring + * the command line rather than not booting. + */ + prom_printf("WARNING: Ignoring cmdline option disable_radix\n"); + } + support->radix_mmu = true; + break; + case OV5_FEAT(OV5_MMU_HASH): + prom_debug("MMU - hash only\n"); + support->hash_mmu = true; + break; + default: + prom_debug("Unknown mmu support option: 0x%x\n", val); + break; + } +} + +static void __init prom_parse_platform_support(u8 index, u8 val, + struct platform_support *support) +{ + switch (index) { + case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */ + prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support); + break; + case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */ + if (val & OV5_FEAT(OV5_RADIX_GTSE)) { + prom_debug("Radix - GTSE supported\n"); + support->radix_gtse = true; + } + break; + } +} + +static void __init prom_check_platform_support(void) +{ + struct platform_support supported = { + .hash_mmu = false, + .radix_mmu = false, + .radix_gtse = false + }; + int prop_len = prom_getproplen(prom.chosen, + "ibm,arch-vec-5-platform-support"); + if (prop_len > 1) { + int i; + u8 vec[prop_len]; + prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n", + prop_len); + prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", + &vec, sizeof(vec)); + for (i = 0; i < prop_len; i += 2) { + prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 + , vec[i] + , vec[i + 1]); + prom_parse_platform_support(vec[i], vec[i + 1], + &supported); + } + } + + if (supported.radix_mmu && supported.radix_gtse) { + /* Radix preferred - but we require GTSE for now */ + prom_debug("Asking for radix with GTSE\n"); + ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX); + ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE); + } else if (supported.hash_mmu) { + /* Default to hash mmu (if we can) */ + prom_debug("Asking for hash\n"); + ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH); + } else { + /* We're probably on a legacy hypervisor */ + prom_debug("Assuming legacy hash support\n"); + } +} static void __init prom_send_capabilities(void) { @@ -997,6 +1100,9 @@ static void __init prom_send_capabilities(void) prom_arg_t ret; u32 cores; + /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */ + prom_check_platform_support(); + root = call_prom("open", 1, 1, ADDR("/")); if (root != 0) { /* We need to tell the FW about the number of cores we support. @@ -2993,6 +3099,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, */ prom_check_initrd(r3, r4); + /* + * Do early parsing of command line + */ + early_cmdline_parse(); + #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) /* * On pSeries, inform the firmware about our capabilities @@ -3009,11 +3120,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, copy_and_flush(0, kbase, 0x100, 0); /* - * Do early parsing of command line - */ - early_cmdline_parse(); - - /* * Initialize memory management within prom_init */ prom_init_mem(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index adf2084f214b..f997154dfc41 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -236,6 +236,15 @@ static void cpu_ready_for_interrupts(void) mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3); } + /* + * Fixup HFSCR:TM based on CPU features. The bit is set by our + * early asm init because at that point we haven't updated our + * CPU features from firmware and device-tree. Here we have, + * so let's do it. + */ + if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP)) + mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); + /* Set IR and DR in PACA MSR */ get_paca()->kernel_msr = MSR_KERNEL; } @@ -408,7 +417,10 @@ static void init_cache_info(struct ppc_cache_info *info, u32 size, u32 lsize, info->line_size = lsize; info->block_size = bsize; info->log_block_size = __ilog2(bsize); - info->blocks_per_page = PAGE_SIZE / bsize; + if (bsize) + info->blocks_per_page = PAGE_SIZE / bsize; + else + info->blocks_per_page = 0; if (sets == 0) info->assoc = 0xffff; diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 46f89e66a273..d68ed1f004a3 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -787,24 +787,21 @@ static struct sched_domain_topology_level powerpc_topology[] = { { NULL, }, }; -void __init smp_cpus_done(unsigned int max_cpus) +static __init long smp_setup_cpu_workfn(void *data __always_unused) { - cpumask_var_t old_mask; + smp_ops->setup_cpu(boot_cpuid); + return 0; +} - /* We want the setup_cpu() here to be called from CPU 0, but our - * init thread may have been "borrowed" by another CPU in the meantime - * se we pin us down to CPU 0 for a short while +void __init smp_cpus_done(unsigned int max_cpus) +{ + /* + * We want the setup_cpu() here to be called on the boot CPU, but + * init might run on any CPU, so make sure it's invoked on the boot + * CPU. */ - alloc_cpumask_var(&old_mask, GFP_NOWAIT); - cpumask_copy(old_mask, ¤t->cpus_allowed); - set_cpus_allowed_ptr(current, cpumask_of(boot_cpuid)); - if (smp_ops && smp_ops->setup_cpu) - smp_ops->setup_cpu(boot_cpuid); - - set_cpus_allowed_ptr(current, old_mask); - - free_cpumask_var(old_mask); + work_on_cpu_safe(boot_cpuid, smp_setup_cpu_workfn, NULL); if (smp_ops && smp_ops->bringup_done) smp_ops->bringup_done(); @@ -812,7 +809,6 @@ void __init smp_cpus_done(unsigned int max_cpus) dump_numa_cpu_topology(); set_sched_topology(powerpc_topology); - } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 07b90725855e..2b33cfaac7b8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -995,8 +995,10 @@ static void __init init_decrementer_clockevent(void) decrementer_clockevent.max_delta_ns = clockevent_delta2ns(decrementer_max, &decrementer_clockevent); + decrementer_clockevent.max_delta_ticks = decrementer_max; decrementer_clockevent.min_delta_ns = clockevent_delta2ns(2, &decrementer_clockevent); + decrementer_clockevent.min_delta_ticks = 2; register_decrementer_clockevent(cpu); } diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 7394b770ae1f..1c24c894c908 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -312,6 +312,8 @@ SECTIONS NOSAVE_DATA } + BUG_TABLE + . = ALIGN(PAGE_SIZE); _edata = .; PROVIDE32 (edata = .); diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index f3158fb16de3..710e491206ed 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -601,7 +601,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, hva, NULL, NULL); if (ptep) { pte = kvmppc_read_update_linux_pte(ptep, 1); - if (pte_write(pte)) + if (__pte_write(pte)) write_ok = 1; } local_irq_restore(flags); @@ -1487,6 +1487,10 @@ long kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm, /* start new resize */ resize = kzalloc(sizeof(*resize), GFP_KERNEL); + if (!resize) { + ret = -ENOMEM; + goto out; + } resize->order = shift; resize->kvm = kvm; INIT_WORK(&resize->work, resize_hpt_prepare_work); diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 6fca970373ee..ce6f2121fffe 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -256,7 +256,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, } pte = kvmppc_read_update_linux_pte(ptep, writing); if (pte_present(pte) && !pte_protnone(pte)) { - if (writing && !pte_write(pte)) + if (writing && !__pte_write(pte)) /* make the actual HPTE be read-only */ ptel = hpte_make_readonly(ptel); is_ci = pte_ci(pte); diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 0e649d72fe8d..ed7dfce331e0 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -14,12 +14,13 @@ obj-y += string.o alloc.o crtsavres.o code-patching.o \ obj-$(CONFIG_PPC32) += div64.o copy_32.o -obj64-y += copypage_64.o copyuser_64.o usercopy_64.o mem_64.o hweight_64.o \ +obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \ copyuser_power7.o string_64.o copypage_power7.o memcpy_power7.o \ memcpy_64.o memcmp_64.o obj64-$(CONFIG_SMP) += locks.o obj64-$(CONFIG_ALTIVEC) += vmx-helper.o +obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o obj-y += checksum_$(BITS).o checksum_wrappers.o diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index ff0d894d7ff9..8aedbb5f4b86 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S @@ -477,18 +477,6 @@ _GLOBAL(__copy_tofrom_user) bdnz 130b /* then clear out the destination: r3 bytes starting at 4(r6) */ 132: mfctr r3 - srwi. r0,r3,2 - li r9,0 - mtctr r0 - beq 113f -112: stwu r9,4(r6) - bdnz 112b -113: andi. r0,r3,3 - mtctr r0 - beq 120f -114: stb r9,4(r6) - addi r6,r6,1 - bdnz 114b 120: blr EX_TABLE(30b,108b) @@ -497,7 +485,5 @@ _GLOBAL(__copy_tofrom_user) EX_TABLE(41b,111b) EX_TABLE(130b,132b) EX_TABLE(131b,120b) - EX_TABLE(112b,120b) - EX_TABLE(114b,120b) EXPORT_SYMBOL(__copy_tofrom_user) diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index aee6e24e81ab..08da06e1bd72 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -319,32 +319,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD) blr /* - * here we have trapped again, need to clear ctr bytes starting at r3 + * here we have trapped again, amount remaining is in ctr. */ -143: mfctr r5 - li r0,0 - mr r4,r3 - mr r3,r5 /* return the number of bytes not copied */ -1: andi. r9,r4,7 - beq 3f -90: stb r0,0(r4) - addic. r5,r5,-1 - addi r4,r4,1 - bne 1b - blr -3: cmpldi cr1,r5,8 - srdi r9,r5,3 - andi. r5,r5,7 - blt cr1,93f - mtctr r9 -91: std r0,0(r4) - addi r4,r4,8 - bdnz 91b -93: beqlr - mtctr r5 -92: stb r0,0(r4) - addi r4,r4,1 - bdnz 92b +143: mfctr r3 blr /* @@ -389,10 +366,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD) ld r5,-8(r1) add r6,r6,r5 subf r3,r3,r6 /* #bytes not copied */ -190: -191: -192: - blr /* #bytes not copied in r3 */ + blr EX_TABLE(20b,120b) EX_TABLE(220b,320b) @@ -451,9 +425,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD) EX_TABLE(88b,188b) EX_TABLE(43b,143b) EX_TABLE(89b,189b) - EX_TABLE(90b,190b) - EX_TABLE(91b,191b) - EX_TABLE(92b,192b) /* * Routine to copy a whole page of data, optimized for POWER4. diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 846dba2c6360..9c542ec70c5b 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1799,8 +1799,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) goto instr_done; case LARX: - if (regs->msr & MSR_LE) - return 0; if (op.ea & (size - 1)) break; /* can't handle misaligned */ if (!address_ok(regs, op.ea, size)) @@ -1823,8 +1821,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) goto ldst_done; case STCX: - if (regs->msr & MSR_LE) - return 0; if (op.ea & (size - 1)) break; /* can't handle misaligned */ if (!address_ok(regs, op.ea, size)) @@ -1849,8 +1845,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) goto ldst_done; case LOAD: - if (regs->msr & MSR_LE) - return 0; err = read_mem(®s->gpr[op.reg], op.ea, size, regs); if (!err) { if (op.type & SIGNEXT) @@ -1862,8 +1856,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) #ifdef CONFIG_PPC_FPU case LOAD_FP: - if (regs->msr & MSR_LE) - return 0; if (size == 4) err = do_fp_load(op.reg, do_lfs, op.ea, size, regs); else @@ -1872,15 +1864,11 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) #endif #ifdef CONFIG_ALTIVEC case LOAD_VMX: - if (regs->msr & MSR_LE) - return 0; err = do_vec_load(op.reg, do_lvx, op.ea & ~0xfUL, regs); goto ldst_done; #endif #ifdef CONFIG_VSX case LOAD_VSX: - if (regs->msr & MSR_LE) - return 0; err = do_vsx_load(op.reg, do_lxvd2x, op.ea, regs); goto ldst_done; #endif @@ -1903,8 +1891,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) goto instr_done; case STORE: - if (regs->msr & MSR_LE) - return 0; if ((op.type & UPDATE) && size == sizeof(long) && op.reg == 1 && op.update_reg == 1 && !(regs->msr & MSR_PR) && @@ -1917,8 +1903,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) #ifdef CONFIG_PPC_FPU case STORE_FP: - if (regs->msr & MSR_LE) - return 0; if (size == 4) err = do_fp_store(op.reg, do_stfs, op.ea, size, regs); else @@ -1927,15 +1911,11 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) #endif #ifdef CONFIG_ALTIVEC case STORE_VMX: - if (regs->msr & MSR_LE) - return 0; err = do_vec_store(op.reg, do_stvx, op.ea & ~0xfUL, regs); goto ldst_done; #endif #ifdef CONFIG_VSX case STORE_VSX: - if (regs->msr & MSR_LE) - return 0; err = do_vsx_store(op.reg, do_stxvd2x, op.ea, regs); goto ldst_done; #endif diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c new file mode 100644 index 000000000000..2534c1447554 --- /dev/null +++ b/arch/powerpc/lib/test_emulate_step.c @@ -0,0 +1,434 @@ +/* + * Simple sanity test for emulate_step load/store instructions. + * + * Copyright IBM Corp. 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#define pr_fmt(fmt) "emulate_step_test: " fmt + +#include <linux/ptrace.h> +#include <asm/sstep.h> +#include <asm/ppc-opcode.h> + +#define IMM_L(i) ((uintptr_t)(i) & 0xffff) + +/* + * Defined with TEST_ prefix so it does not conflict with other + * definitions. + */ +#define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \ + ___PPC_RA(base) | IMM_L(i)) +#define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \ + ___PPC_RA(base) | IMM_L(i)) +#define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \ + ___PPC_RA(base) | ((i) & 0xfffc)) +#define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \ + ___PPC_RA(a) | ___PPC_RB(b) | \ + __PPC_EH(eh)) +#define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \ + ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b)) +#define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b)) + + +static void __init init_pt_regs(struct pt_regs *regs) +{ + static unsigned long msr; + static bool msr_cached; + + memset(regs, 0, sizeof(struct pt_regs)); + + if (likely(msr_cached)) { + regs->msr = msr; + return; + } + + asm volatile("mfmsr %0" : "=r"(regs->msr)); + + regs->msr |= MSR_FP; + regs->msr |= MSR_VEC; + regs->msr |= MSR_VSX; + + msr = regs->msr; + msr_cached = true; +} + +static void __init show_result(char *ins, char *result) +{ + pr_info("%-14s : %s\n", ins, result); +} + +static void __init test_ld(void) +{ + struct pt_regs regs; + unsigned long a = 0x23; + int stepped = -1; + + init_pt_regs(®s); + regs.gpr[3] = (unsigned long) &a; + + /* ld r5, 0(r3) */ + stepped = emulate_step(®s, TEST_LD(5, 3, 0)); + + if (stepped == 1 && regs.gpr[5] == a) + show_result("ld", "PASS"); + else + show_result("ld", "FAIL"); +} + +static void __init test_lwz(void) +{ + struct pt_regs regs; + unsigned int a = 0x4545; + int stepped = -1; + + init_pt_regs(®s); + regs.gpr[3] = (unsigned long) &a; + + /* lwz r5, 0(r3) */ + stepped = emulate_step(®s, TEST_LWZ(5, 3, 0)); + + if (stepped == 1 && regs.gpr[5] == a) + show_result("lwz", "PASS"); + else + show_result("lwz", "FAIL"); +} + +static void __init test_lwzx(void) +{ + struct pt_regs regs; + unsigned int a[3] = {0x0, 0x0, 0x1234}; + int stepped = -1; + + init_pt_regs(®s); + regs.gpr[3] = (unsigned long) a; + regs.gpr[4] = 8; + regs.gpr[5] = 0x8765; + + /* lwzx r5, r3, r4 */ + stepped = emulate_step(®s, TEST_LWZX(5, 3, 4)); + if (stepped == 1 && regs.gpr[5] == a[2]) + show_result("lwzx", "PASS"); + else + show_result("lwzx", "FAIL"); +} + +static void __init test_std(void) +{ + struct pt_regs regs; + unsigned long a = 0x1234; + int stepped = -1; + + init_pt_regs(®s); + regs.gpr[3] = (unsigned long) &a; + regs.gpr[5] = 0x5678; + + /* std r5, 0(r3) */ + stepped = emulate_step(®s, TEST_STD(5, 3, 0)); + if (stepped == 1 || regs.gpr[5] == a) + show_result("std", "PASS"); + else + show_result("std", "FAIL"); +} + +static void __init test_ldarx_stdcx(void) +{ + struct pt_regs regs; + unsigned long a = 0x1234; + int stepped = -1; + unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */ + + init_pt_regs(®s); + asm volatile("mfcr %0" : "=r"(regs.ccr)); + + + /*** ldarx ***/ + + regs.gpr[3] = (unsigned long) &a; + regs.gpr[4] = 0; + regs.gpr[5] = 0x5678; + + /* ldarx r5, r3, r4, 0 */ + stepped = emulate_step(®s, TEST_LDARX(5, 3, 4, 0)); + + /* + * Don't touch 'a' here. Touching 'a' can do Load/store + * of 'a' which result in failure of subsequent stdcx. + * Instead, use hardcoded value for comparison. + */ + if (stepped <= 0 || regs.gpr[5] != 0x1234) { + show_result("ldarx / stdcx.", "FAIL (ldarx)"); + return; + } + + + /*** stdcx. ***/ + + regs.gpr[5] = 0x9ABC; + + /* stdcx. r5, r3, r4 */ + stepped = emulate_step(®s, TEST_STDCX(5, 3, 4)); + + /* + * Two possible scenarios that indicates successful emulation + * of stdcx. : + * 1. Reservation is active and store is performed. In this + * case cr0.eq bit will be set to 1. + * 2. Reservation is not active and store is not performed. + * In this case cr0.eq bit will be set to 0. + */ + if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq)) + || (regs.gpr[5] != a && !(regs.ccr & cr0_eq)))) + show_result("ldarx / stdcx.", "PASS"); + else + show_result("ldarx / stdcx.", "FAIL (stdcx.)"); +} + +#ifdef CONFIG_PPC_FPU +static void __init test_lfsx_stfsx(void) +{ + struct pt_regs regs; + union { + float a; + int b; + } c; + int cached_b; + int stepped = -1; + + init_pt_regs(®s); + + + /*** lfsx ***/ + + c.a = 123.45; + cached_b = c.b; + + regs.gpr[3] = (unsigned long) &c.a; + regs.gpr[4] = 0; + + /* lfsx frt10, r3, r4 */ + stepped = emulate_step(®s, TEST_LFSX(10, 3, 4)); + + if (stepped == 1) + show_result("lfsx", "PASS"); + else + show_result("lfsx", "FAIL"); + + + /*** stfsx ***/ + + c.a = 678.91; + + /* stfsx frs10, r3, r4 */ + stepped = emulate_step(®s, TEST_STFSX(10, 3, 4)); + + if (stepped == 1 && c.b == cached_b) + show_result("stfsx", "PASS"); + else + show_result("stfsx", "FAIL"); +} + +static void __init test_lfdx_stfdx(void) +{ + struct pt_regs regs; + union { + double a; + long b; + } c; + long cached_b; + int stepped = -1; + + init_pt_regs(®s); + + + /*** lfdx ***/ + + c.a = 123456.78; + cached_b = c.b; + + regs.gpr[3] = (unsigned long) &c.a; + regs.gpr[4] = 0; + + /* lfdx frt10, r3, r4 */ + stepped = emulate_step(®s, TEST_LFDX(10, 3, 4)); + + if (stepped == 1) + show_result("lfdx", "PASS"); + else + show_result("lfdx", "FAIL"); + + + /*** stfdx ***/ + + c.a = 987654.32; + + /* stfdx frs10, r3, r4 */ + stepped = emulate_step(®s, TEST_STFDX(10, 3, 4)); + + if (stepped == 1 && c.b == cached_b) + show_result("stfdx", "PASS"); + else + show_result("stfdx", "FAIL"); +} +#else +static void __init test_lfsx_stfsx(void) +{ + show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)"); + show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)"); +} + +static void __init test_lfdx_stfdx(void) +{ + show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)"); + show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)"); +} +#endif /* CONFIG_PPC_FPU */ + +#ifdef CONFIG_ALTIVEC +static void __init test_lvx_stvx(void) +{ + struct pt_regs regs; + union { + vector128 a; + u32 b[4]; + } c; + u32 cached_b[4]; + int stepped = -1; + + init_pt_regs(®s); + + + /*** lvx ***/ + + cached_b[0] = c.b[0] = 923745; + cached_b[1] = c.b[1] = 2139478; + cached_b[2] = c.b[2] = 9012; + cached_b[3] = c.b[3] = 982134; + + regs.gpr[3] = (unsigned long) &c.a; + regs.gpr[4] = 0; + + /* lvx vrt10, r3, r4 */ + stepped = emulate_step(®s, TEST_LVX(10, 3, 4)); + + if (stepped == 1) + show_result("lvx", "PASS"); + else + show_result("lvx", "FAIL"); + + + /*** stvx ***/ + + c.b[0] = 4987513; + c.b[1] = 84313948; + c.b[2] = 71; + c.b[3] = 498532; + + /* stvx vrs10, r3, r4 */ + stepped = emulate_step(®s, TEST_STVX(10, 3, 4)); + + if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && + cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) + show_result("stvx", "PASS"); + else + show_result("stvx", "FAIL"); +} +#else +static void __init test_lvx_stvx(void) +{ + show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)"); + show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)"); +} +#endif /* CONFIG_ALTIVEC */ + +#ifdef CONFIG_VSX +static void __init test_lxvd2x_stxvd2x(void) +{ + struct pt_regs regs; + union { + vector128 a; + u32 b[4]; + } c; + u32 cached_b[4]; + int stepped = -1; + + init_pt_regs(®s); + + + /*** lxvd2x ***/ + + cached_b[0] = c.b[0] = 18233; + cached_b[1] = c.b[1] = 34863571; + cached_b[2] = c.b[2] = 834; + cached_b[3] = c.b[3] = 6138911; + + regs.gpr[3] = (unsigned long) &c.a; + regs.gpr[4] = 0; + + /* lxvd2x vsr39, r3, r4 */ + stepped = emulate_step(®s, TEST_LXVD2X(39, 3, 4)); + + if (stepped == 1) + show_result("lxvd2x", "PASS"); + else + show_result("lxvd2x", "FAIL"); + + + /*** stxvd2x ***/ + + c.b[0] = 21379463; + c.b[1] = 87; + c.b[2] = 374234; + c.b[3] = 4; + + /* stxvd2x vsr39, r3, r4 */ + stepped = emulate_step(®s, TEST_STXVD2X(39, 3, 4)); + + if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && + cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) + show_result("stxvd2x", "PASS"); + else + show_result("stxvd2x", "FAIL"); +} +#else +static void __init test_lxvd2x_stxvd2x(void) +{ + show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)"); + show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)"); +} +#endif /* CONFIG_VSX */ + +static int __init test_emulate_step(void) +{ + test_ld(); + test_lwz(); + test_lwzx(); + test_std(); + test_ldarx_stdcx(); + test_lfsx_stfsx(); + test_lfdx_stfdx(); + test_lvx_stvx(); + test_lxvd2x_stxvd2x(); + + return 0; +} +late_initcall(test_emulate_step); diff --git a/arch/powerpc/lib/usercopy_64.c b/arch/powerpc/lib/usercopy_64.c deleted file mode 100644 index 9bd3a3dad78d..000000000000 --- a/arch/powerpc/lib/usercopy_64.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Functions which are too large to be inlined. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include <linux/module.h> -#include <linux/uaccess.h> - -unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_READ, from, n))) - n = __copy_from_user(to, from, n); - else - memset(to, 0, n); - return n; -} - -unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_WRITE, to, n))) - n = __copy_to_user(to, from, n); - return n; -} - -unsigned long copy_in_user(void __user *to, const void __user *from, - unsigned long n) -{ - might_sleep(); - if (likely(access_ok(VERIFY_READ, from, n) && - access_ok(VERIFY_WRITE, to, n))) - n =__copy_tofrom_user(to, from, n); - return n; -} - -EXPORT_SYMBOL(copy_from_user); -EXPORT_SYMBOL(copy_to_user); -EXPORT_SYMBOL(copy_in_user); - diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index cc332608e656..65bb8f33b399 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -638,6 +638,10 @@ static void native_flush_hash_range(unsigned long number, int local) unsigned long psize = batch->psize; int ssize = batch->ssize; int i; + unsigned int use_local; + + use_local = local && mmu_has_feature(MMU_FTR_TLBIEL) && + mmu_psize_defs[psize].tlbiel && !cxl_ctx_in_use(); local_irq_save(flags); @@ -667,8 +671,7 @@ static void native_flush_hash_range(unsigned long number, int local) } pte_iterate_hashed_end(); } - if (mmu_has_feature(MMU_FTR_TLBIEL) && - mmu_psize_defs[psize].tlbiel && local) { + if (use_local) { asm volatile("ptesync":::"memory"); for (i = 0; i < number; i++) { vpn = batch->vpn[i]; diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 6aa3b76aa0d6..c22f207aa656 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -356,25 +356,48 @@ static void early_check_vec5(void) unsigned long root, chosen; int size; const u8 *vec5; + u8 mmu_supported; root = of_get_flat_dt_root(); chosen = of_get_flat_dt_subnode_by_name(root, "chosen"); - if (chosen == -FDT_ERR_NOTFOUND) + if (chosen == -FDT_ERR_NOTFOUND) { + cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX; return; + } vec5 = of_get_flat_dt_prop(chosen, "ibm,architecture-vec-5", &size); - if (!vec5) + if (!vec5) { + cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX; return; - if (size <= OV5_INDX(OV5_MMU_RADIX_300) || - !(vec5[OV5_INDX(OV5_MMU_RADIX_300)] & OV5_FEAT(OV5_MMU_RADIX_300))) - /* Hypervisor doesn't support radix */ + } + if (size <= OV5_INDX(OV5_MMU_SUPPORT)) { cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX; + return; + } + + /* Check for supported configuration */ + mmu_supported = vec5[OV5_INDX(OV5_MMU_SUPPORT)] & + OV5_FEAT(OV5_MMU_SUPPORT); + if (mmu_supported == OV5_FEAT(OV5_MMU_RADIX)) { + /* Hypervisor only supports radix - check enabled && GTSE */ + if (!early_radix_enabled()) { + pr_warn("WARNING: Ignoring cmdline option disable_radix\n"); + } + if (!(vec5[OV5_INDX(OV5_RADIX_GTSE)] & + OV5_FEAT(OV5_RADIX_GTSE))) { + pr_warn("WARNING: Hypervisor doesn't support RADIX with GTSE\n"); + } + /* Do radix anyway - the hypervisor said we had to */ + cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX; + } else if (mmu_supported == OV5_FEAT(OV5_MMU_HASH)) { + /* Hypervisor only supports hash - disable radix */ + cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX; + } } void __init mmu_early_init_devtree(void) { /* Disable radix mode based on kernel command line. */ - /* We don't yet have the machinery to do radix as a guest. */ - if (disable_radix || !(mfmsr() & MSR_HV)) + if (disable_radix) cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX; /* @@ -383,7 +406,7 @@ void __init mmu_early_init_devtree(void) * even though the ibm,architecture-vec-5 property created by * skiboot doesn't have the necessary bits set. */ - if (early_radix_enabled() && !(mfmsr() & MSR_HV)) + if (!(mfmsr() & MSR_HV)) early_check_vec5(); if (early_radix_enabled()) diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 2a590a98e652..c28165d8970b 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c @@ -186,6 +186,10 @@ static void __init radix_init_pgtable(void) */ register_process_table(__pa(process_tb), 0, PRTB_SIZE_SHIFT - 12); pr_info("Process table %p and radix root for kernel: %p\n", process_tb, init_mm.pgd); + asm volatile("ptesync" : : : "memory"); + asm volatile(PPC_TLBIE_5(%0,%1,2,1,1) : : + "r" (TLBIEL_INVAL_SET_LPID), "r" (0)); + asm volatile("eieio; tlbsync; ptesync" : : : "memory"); } static void __init radix_init_partition_table(void) diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 595dd718ea87..2ff13249f87a 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -188,6 +188,8 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) sdsync = POWER7P_MMCRA_SDAR_VALID; else if (ppmu->flags & PPMU_ALT_SIPR) sdsync = POWER6_MMCRA_SDSYNC; + else if (ppmu->flags & PPMU_NO_SIAR) + sdsync = MMCRA_SAMPLE_ENABLE; else sdsync = MMCRA_SDSYNC; diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c index e79fb5fb817d..cd951fd231c4 100644 --- a/arch/powerpc/perf/isa207-common.c +++ b/arch/powerpc/perf/isa207-common.c @@ -65,12 +65,41 @@ static bool is_event_valid(u64 event) return !(event & ~valid_mask); } -static u64 mmcra_sdar_mode(u64 event) +static inline bool is_event_marked(u64 event) { - if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1)) - return p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT; + if (event & EVENT_IS_MARKED) + return true; + + return false; +} - return MMCRA_SDAR_MODE_TLB; +static void mmcra_sdar_mode(u64 event, unsigned long *mmcra) +{ + /* + * MMCRA[SDAR_MODE] specifices how the SDAR should be updated in + * continous sampling mode. + * + * Incase of Power8: + * MMCRA[SDAR_MODE] will be programmed as "0b01" for continous sampling + * mode and will be un-changed when setting MMCRA[63] (Marked events). + * + * Incase of Power9: + * Marked event: MMCRA[SDAR_MODE] will be set to 0b00 ('No Updates'), + * or if group already have any marked events. + * Non-Marked events (for DD1): + * MMCRA[SDAR_MODE] will be set to 0b01 + * For rest + * MMCRA[SDAR_MODE] will be set from event code. + */ + if (cpu_has_feature(CPU_FTR_ARCH_300)) { + if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE)) + *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES; + else if (!cpu_has_feature(CPU_FTR_POWER9_DD1)) + *mmcra |= p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT; + else if (cpu_has_feature(CPU_FTR_POWER9_DD1)) + *mmcra |= MMCRA_SDAR_MODE_TLB; + } else + *mmcra |= MMCRA_SDAR_MODE_TLB; } static u64 thresh_cmp_val(u64 value) @@ -180,7 +209,7 @@ int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) value |= CNST_L1_QUAL_VAL(cache); } - if (event & EVENT_IS_MARKED) { + if (is_event_marked(event)) { mask |= CNST_SAMPLE_MASK; value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT); } @@ -276,7 +305,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev, } /* In continuous sampling mode, update SDAR on TLB miss */ - mmcra |= mmcra_sdar_mode(event[i]); + mmcra_sdar_mode(event[i], &mmcra); if (event[i] & EVENT_IS_L1) { cache = event[i] >> EVENT_CACHE_SEL_SHIFT; @@ -285,7 +314,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev, mmcr1 |= (cache & 1) << MMCR1_DC_QUAL_SHIFT; } - if (event[i] & EVENT_IS_MARKED) { + if (is_event_marked(event[i])) { mmcra |= MMCRA_SAMPLE_ENABLE; val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK; diff --git a/arch/powerpc/perf/isa207-common.h b/arch/powerpc/perf/isa207-common.h index cf9bd8990159..899210f14ee4 100644 --- a/arch/powerpc/perf/isa207-common.h +++ b/arch/powerpc/perf/isa207-common.h @@ -246,6 +246,7 @@ #define MMCRA_THR_CMP_SHIFT 32 #define MMCRA_SDAR_MODE_SHIFT 42 #define MMCRA_SDAR_MODE_TLB (1ull << MMCRA_SDAR_MODE_SHIFT) +#define MMCRA_SDAR_MODE_NO_UPDATES ~(0x3ull << MMCRA_SDAR_MODE_SHIFT) #define MMCRA_IFM_SHIFT 30 /* MMCR1 Threshold Compare bit constant for power9 */ diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 6693f75e93d1..da8a0f7a035c 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -39,8 +39,8 @@ opal_tracepoint_refcount: BEGIN_FTR_SECTION; \ b 1f; \ END_FTR_SECTION(0, 1); \ - ld r12,opal_tracepoint_refcount@toc(r2); \ - cmpdi r12,0; \ + ld r11,opal_tracepoint_refcount@toc(r2); \ + cmpdi r11,0; \ bne- LABEL; \ 1: diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 86d9fde93c17..e0f856bfbfe8 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -395,7 +395,6 @@ static int opal_recover_mce(struct pt_regs *regs, struct machine_check_event *evt) { int recovered = 0; - uint64_t ea = get_mce_fault_addr(evt); if (!(regs->msr & MSR_RI)) { /* If MSR_RI isn't set, we cannot recover */ @@ -404,26 +403,18 @@ static int opal_recover_mce(struct pt_regs *regs, } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) { /* Platform corrected itself */ recovered = 1; - } else if (ea && !is_kernel_addr(ea)) { + } else if (evt->severity == MCE_SEV_FATAL) { + /* Fatal machine check */ + pr_err("Machine check interrupt is fatal\n"); + recovered = 0; + } else if ((evt->severity == MCE_SEV_ERROR_SYNC) && + (user_mode(regs) && !is_global_init(current))) { /* - * Faulting address is not in kernel text. We should be fine. - * We need to find which process uses this address. * For now, kill the task if we have received exception when * in userspace. * * TODO: Queue up this address for hwpoisioning later. */ - if (user_mode(regs) && !is_global_init(current)) { - _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip); - recovered = 1; - } else - recovered = 0; - } else if (user_mode(regs) && !is_global_init(current) && - evt->severity == MCE_SEV_ERROR_SYNC) { - /* - * If we have received a synchronous error when in userspace - * kill the task. - */ _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip); recovered = 1; } diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 6901a06da2f9..e36738291c32 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1775,17 +1775,20 @@ static u64 pnv_pci_ioda_dma_get_required_mask(struct pci_dev *pdev) } static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, - struct pci_bus *bus) + struct pci_bus *bus, + bool add_to_group) { struct pci_dev *dev; list_for_each_entry(dev, &bus->devices, bus_list) { set_iommu_table_base(&dev->dev, pe->table_group.tables[0]); set_dma_offset(&dev->dev, pe->tce_bypass_base); - iommu_add_device(&dev->dev); + if (add_to_group) + iommu_add_device(&dev->dev); if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate) - pnv_ioda_setup_bus_dma(pe, dev->subordinate); + pnv_ioda_setup_bus_dma(pe, dev->subordinate, + add_to_group); } } @@ -2191,7 +2194,7 @@ found: set_iommu_table_base(&pe->pdev->dev, tbl); iommu_add_device(&pe->pdev->dev); } else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)) - pnv_ioda_setup_bus_dma(pe, pe->pbus); + pnv_ioda_setup_bus_dma(pe, pe->pbus, true); return; fail: @@ -2426,6 +2429,8 @@ static void pnv_ioda2_take_ownership(struct iommu_table_group *table_group) pnv_pci_ioda2_set_bypass(pe, false); pnv_pci_ioda2_unset_window(&pe->table_group, 0); + if (pe->pbus) + pnv_ioda_setup_bus_dma(pe, pe->pbus, false); pnv_ioda2_table_free(tbl); } @@ -2435,6 +2440,8 @@ static void pnv_ioda2_release_ownership(struct iommu_table_group *table_group) table_group); pnv_pci_ioda2_setup_default_config(pe); + if (pe->pbus) + pnv_ioda_setup_bus_dma(pe, pe->pbus, false); } static struct iommu_table_group_ops pnv_pci_ioda2_ops = { @@ -2624,6 +2631,9 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset, level_shift = entries_shift + 3; level_shift = max_t(unsigned, level_shift, PAGE_SHIFT); + if ((level_shift - 3) * levels + page_shift >= 60) + return -EINVAL; + /* Allocate TCE table */ addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift, levels, tce_table_size, &offset, &total_allocated); @@ -2728,7 +2738,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, if (pe->flags & PNV_IODA_PE_DEV) iommu_add_device(&pe->pdev->dev); else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)) - pnv_ioda_setup_bus_dma(pe, pe->pbus); + pnv_ioda_setup_bus_dma(pe, pe->pbus, true); } #ifdef CONFIG_PCI_MSI diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 251060cf1713..8b1fe895daa3 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -751,7 +751,9 @@ void __init hpte_init_pseries(void) mmu_hash_ops.flush_hash_range = pSeries_lpar_flush_hash_range; mmu_hash_ops.hpte_clear_all = pseries_hpte_clear_all; mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate; - mmu_hash_ops.resize_hpt = pseries_lpar_resize_hpt; + + if (firmware_has_feature(FW_FEATURE_HPT_RESIZE)) + mmu_hash_ops.resize_hpt = pseries_lpar_resize_hpt; } void radix_init_pseries(void) diff --git a/arch/powerpc/purgatory/trampoline.S b/arch/powerpc/purgatory/trampoline.S index f9760ccf4032..3696ea6c4826 100644 --- a/arch/powerpc/purgatory/trampoline.S +++ b/arch/powerpc/purgatory/trampoline.S @@ -116,13 +116,13 @@ dt_offset: .data .balign 8 -.globl sha256_digest -sha256_digest: +.globl purgatory_sha256_digest +purgatory_sha256_digest: .skip 32 - .size sha256_digest, . - sha256_digest + .size purgatory_sha256_digest, . - purgatory_sha256_digest .balign 8 -.globl sha_regions -sha_regions: +.globl purgatory_sha_regions +purgatory_sha_regions: .skip 8 * 2 * 16 - .size sha_regions, . - sha_regions + .size purgatory_sha_regions, . - purgatory_sha_regions diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index ada29eaed6e2..f523ac883150 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -274,7 +274,9 @@ failed: if (bank->disk->major > 0) unregister_blkdev(bank->disk->major, bank->disk->disk_name); - del_gendisk(bank->disk); + if (bank->disk->flags & GENHD_FL_UP) + del_gendisk(bank->disk); + put_disk(bank->disk); } device->dev.platform_data = NULL; if (bank->io_addr != 0) @@ -299,6 +301,7 @@ axon_ram_remove(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_ecc); free_irq(bank->irq_id, device); del_gendisk(bank->disk); + put_disk(bank->disk); iounmap((void __iomem *) bank->io_addr); kfree(bank); diff --git a/arch/powerpc/sysdev/xics/icp-opal.c b/arch/powerpc/sysdev/xics/icp-opal.c index f9670eabfcfa..b53f80f0b4d8 100644 --- a/arch/powerpc/sysdev/xics/icp-opal.c +++ b/arch/powerpc/sysdev/xics/icp-opal.c @@ -91,6 +91,16 @@ static unsigned int icp_opal_get_irq(void) static void icp_opal_set_cpu_priority(unsigned char cppr) { + /* + * Here be dragons. The caller has asked to allow only IPI's and not + * external interrupts. But OPAL XIVE doesn't support that. So instead + * of allowing no interrupts allow all. That's still not right, but + * currently the only caller who does this is xics_migrate_irqs_away() + * and it works in that case. + */ + if (cppr >= DEFAULT_PRIORITY) + cppr = LOWEST_PRIORITY; + xics_set_base_cppr(cppr); opal_int_set_cppr(cppr); iosync(); diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 69d858e51ac7..23efe4e42172 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -20,6 +20,7 @@ #include <linux/of.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/delay.h> #include <asm/prom.h> #include <asm/io.h> @@ -198,9 +199,6 @@ void xics_migrate_irqs_away(void) /* Remove ourselves from the global interrupt queue */ xics_set_cpu_giq(xics_default_distrib_server, 0); - /* Allow IPIs again... */ - icp_ops->set_priority(DEFAULT_PRIORITY); - for_each_irq_desc(virq, desc) { struct irq_chip *chip; long server; @@ -255,6 +253,19 @@ void xics_migrate_irqs_away(void) unlock: raw_spin_unlock_irqrestore(&desc->lock, flags); } + + /* Allow "sufficient" time to drop any inflight IRQ's */ + mdelay(5); + + /* + * Allow IPIs again. This is done at the very end, after migrating all + * interrupts, the expectation is that we'll only get woken up by an IPI + * interrupt beyond this point, but leave externals masked just to be + * safe. If we're using icp-opal this may actually allow all + * interrupts anyway, but that should be OK. + */ + icp_ops->set_priority(DEFAULT_PRIORITY); + } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild index e256592eb66e..eae2c64cf69d 100644 --- a/arch/s390/Kbuild +++ b/arch/s390/Kbuild @@ -1,7 +1,7 @@ obj-y += kernel/ obj-y += mm/ obj-$(CONFIG_KVM) += kvm/ -obj-$(CONFIG_CRYPTO_HW) += crypto/ +obj-y += crypto/ obj-$(CONFIG_S390_HYPFS_FS) += hypfs/ obj-$(CONFIG_APPLDATA_BASE) += appldata/ obj-y += net/ diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index a2dcef0aacc7..e161fafb495b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -105,6 +105,7 @@ config S390 select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE select ARCH_SAVE_PAGE_KEYS if HIBERNATION select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF @@ -123,8 +124,6 @@ config S390 select GENERIC_TIME_VSYSCALL select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL - select HAVE_ARCH_EARLY_PFN_TO_NID - select HAVE_ARCH_HARDENED_USERCOPY select HAVE_ARCH_JUMP_LABEL select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES select HAVE_ARCH_SECCOMP_FILTER @@ -507,6 +506,21 @@ source kernel/Kconfig.preempt source kernel/Kconfig.hz +config ARCH_RANDOM + def_bool y + prompt "s390 architectural random number generation API" + help + Enable the s390 architectural random number generation API + to provide random data for all consumers within the Linux + kernel. + + When enabled the arch_random_* functions declared in linux/random.h + are implemented. The implementation is based on the s390 CPACF + instruction subfunction TRNG which provides a real true random + number generator. + + If unsure, say Y. + endmenu menu "Memory setup" @@ -537,6 +551,16 @@ config FORCE_MAX_ZONEORDER source "mm/Kconfig" +config MAX_PHYSMEM_BITS + int "Maximum size of supported physical memory in bits (42-53)" + range 42 53 + default "46" + help + This option specifies the maximum supported size of physical memory + in bits. Supported is any size between 2^42 (4TB) and 2^53 (8PB). + Increasing the number of bits also increases the kernel image size. + By default 46 bits (64TB) are supported. + config PACK_STACK def_bool y prompt "Pack kernel stack" @@ -614,7 +638,7 @@ if PCI config PCI_NR_FUNCTIONS int "Maximum number of PCI functions (1-4096)" range 1 4096 - default "64" + default "128" help This allows you to specify the maximum number of PCI functions which this kernel will support. @@ -672,6 +696,16 @@ config EADM_SCH To compile this driver as a module, choose M here: the module will be called eadm_sch. +config VFIO_CCW + def_tristate n + prompt "Support for VFIO-CCW subchannels" + depends on S390_CCW_IOMMU && VFIO_MDEV + help + This driver allows usage of I/O subchannels via VFIO-CCW. + + To compile this driver as a module, choose M here: the + module will be called vfio_ccw. + endmenu menu "Dump support" diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index fa95041fa9f6..33ca29333e18 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c @@ -141,31 +141,34 @@ static void check_ipl_parmblock(void *start, unsigned long size) unsigned long decompress_kernel(void) { - unsigned long output_addr; - unsigned char *output; + void *output, *kernel_end; - output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL; - check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start); - memset(&_bss, 0, &_ebss - &_bss); - free_mem_ptr = (unsigned long)&_end; - free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - output = (unsigned char *) output_addr; + output = (void *) ALIGN((unsigned long) &_end + HEAP_SIZE, PAGE_SIZE); + kernel_end = output + SZ__bss_start; + check_ipl_parmblock((void *) 0, (unsigned long) kernel_end); #ifdef CONFIG_BLK_DEV_INITRD /* * Move the initrd right behind the end of the decompressed - * kernel image. + * kernel image. This also prevents initrd corruption caused by + * bss clearing since kernel_end will always be located behind the + * current bss section.. */ - if (INITRD_START && INITRD_SIZE && - INITRD_START < (unsigned long) output + SZ__bss_start) { - check_ipl_parmblock(output + SZ__bss_start, - INITRD_START + INITRD_SIZE); - memmove(output + SZ__bss_start, - (void *) INITRD_START, INITRD_SIZE); - INITRD_START = (unsigned long) output + SZ__bss_start; + if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) { + check_ipl_parmblock(kernel_end, INITRD_SIZE); + memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE); + INITRD_START = (unsigned long) kernel_end; } #endif + /* + * Clear bss section. free_mem_ptr and free_mem_end_ptr need to be + * initialized afterwards since they reside in bss. + */ + memset(&_bss, 0, &_ebss - &_bss); + free_mem_ptr = (unsigned long) &_end; + free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; + puts("Uncompressing Linux... "); __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); puts("Ok, booting the kernel.\n"); diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig index 143b1e00b818..a5039fa89314 100644 --- a/arch/s390/configs/default_defconfig +++ b/arch/s390/configs/default_defconfig @@ -73,6 +73,7 @@ CONFIG_ZSWAP=y CONFIG_ZBUD=m CONFIG_ZSMALLOC=m CONFIG_ZSMALLOC_STAT=y +CONFIG_DEFERRED_STRUCT_PAGE_INIT=y CONFIG_IDLE_PAGE_TRACKING=y CONFIG_PCI=y CONFIG_PCI_DEBUG=y @@ -609,7 +610,7 @@ CONFIG_SCHED_TRACER=y CONFIG_FTRACE_SYSCALLS=y CONFIG_STACK_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_UPROBE_EVENT=y +CONFIG_UPROBE_EVENTS=y CONFIG_FUNCTION_PROFILER=y CONFIG_HIST_TRIGGERS=y CONFIG_TRACE_ENUM_MAP_FILE=y diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig index f05d2d6e1087..83970b5afb2b 100644 --- a/arch/s390/configs/gcov_defconfig +++ b/arch/s390/configs/gcov_defconfig @@ -72,6 +72,7 @@ CONFIG_ZSWAP=y CONFIG_ZBUD=m CONFIG_ZSMALLOC=m CONFIG_ZSMALLOC_STAT=y +CONFIG_DEFERRED_STRUCT_PAGE_INIT=y CONFIG_IDLE_PAGE_TRACKING=y CONFIG_PCI=y CONFIG_HOTPLUG_PCI=y @@ -560,7 +561,7 @@ CONFIG_SCHED_TRACER=y CONFIG_FTRACE_SYSCALLS=y CONFIG_STACK_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_UPROBE_EVENT=y +CONFIG_UPROBE_EVENTS=y CONFIG_FUNCTION_PROFILER=y CONFIG_HIST_TRIGGERS=y CONFIG_TRACE_ENUM_MAP_FILE=y diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index 2358bf33c5ef..fbc6542aaf59 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig @@ -70,6 +70,7 @@ CONFIG_ZSWAP=y CONFIG_ZBUD=m CONFIG_ZSMALLOC=m CONFIG_ZSMALLOC_STAT=y +CONFIG_DEFERRED_STRUCT_PAGE_INIT=y CONFIG_IDLE_PAGE_TRACKING=y CONFIG_PCI=y CONFIG_HOTPLUG_PCI=y @@ -558,7 +559,7 @@ CONFIG_SCHED_TRACER=y CONFIG_FTRACE_SYSCALLS=y CONFIG_STACK_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_UPROBE_EVENT=y +CONFIG_UPROBE_EVENTS=y CONFIG_FUNCTION_PROFILER=y CONFIG_HIST_TRIGGERS=y CONFIG_TRACE_ENUM_MAP_FILE=y diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig index 4366a3e3e754..e23d97c13735 100644 --- a/arch/s390/configs/zfcpdump_defconfig +++ b/arch/s390/configs/zfcpdump_defconfig @@ -35,7 +35,6 @@ CONFIG_SCSI_ENCLOSURE=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_FC_ATTRS=y -CONFIG_SCSI_SRP_ATTRS=y CONFIG_ZFCP=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set # CONFIG_INPUT_KEYBOARD is not set diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 402c530c6da5..678d9863e3f0 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile @@ -10,5 +10,6 @@ obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o paes_s390.o obj-$(CONFIG_S390_PRNG) += prng.o obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o obj-$(CONFIG_CRYPTO_CRC32_S390) += crc32-vx_s390.o +obj-$(CONFIG_ARCH_RANDOM) += arch_random.o crc32-vx_s390-y := crc32-vx.o crc32le-vx.o crc32be-vx.o diff --git a/arch/s390/crypto/arch_random.c b/arch/s390/crypto/arch_random.c new file mode 100644 index 000000000000..9317b3e645e2 --- /dev/null +++ b/arch/s390/crypto/arch_random.c @@ -0,0 +1,31 @@ +/* + * s390 arch random implementation. + * + * Copyright IBM Corp. 2017 + * Author(s): Harald Freudenberger <freude@de.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/atomic.h> +#include <linux/static_key.h> +#include <asm/cpacf.h> + +DEFINE_STATIC_KEY_FALSE(s390_arch_random_available); + +atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0); +EXPORT_SYMBOL(s390_arch_random_counter); + +static int __init s390_arch_random_init(void) +{ + /* check if subfunction CPACF_PRNO_TRNG is available */ + if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG)) + static_branch_enable(&s390_arch_random_available); + + return 0; +} +arch_initcall(s390_arch_random_init); diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c index d69ea495c4d7..a4e903ed7e21 100644 --- a/arch/s390/crypto/paes_s390.c +++ b/arch/s390/crypto/paes_s390.c @@ -474,8 +474,11 @@ static int ctr_paes_crypt(struct blkcipher_desc *desc, unsigned long modifier, ret = blkcipher_walk_done(desc, walk, nbytes - n); } if (k < n) { - if (__ctr_paes_set_key(ctx) != 0) + if (__ctr_paes_set_key(ctx) != 0) { + if (locked) + spin_unlock(&ctrblk_lock); return blkcipher_walk_done(desc, walk, -EIO); + } } } if (locked) @@ -613,7 +616,7 @@ out_err: module_init(paes_s390_init); module_exit(paes_s390_fini); -MODULE_ALIAS_CRYPTO("aes-all"); +MODULE_ALIAS_CRYPTO("paes"); MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm with protected keys"); MODULE_LICENSE("GPL"); diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index 5a3ec04a7082..3e47c4a0f18b 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c @@ -81,7 +81,7 @@ struct prng_ws_s { u64 byte_counter; }; -struct ppno_ws_s { +struct prno_ws_s { u32 res; u32 reseed_counter; u64 stream_bytes; @@ -93,7 +93,7 @@ struct prng_data_s { struct mutex mutex; union { struct prng_ws_s prngws; - struct ppno_ws_s ppnows; + struct prno_ws_s prnows; }; u8 *buf; u32 rest; @@ -306,12 +306,12 @@ static int __init prng_sha512_selftest(void) 0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 }; u8 buf[sizeof(random)]; - struct ppno_ws_s ws; + struct prno_ws_s ws; memset(&ws, 0, sizeof(ws)); /* initial seed */ - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, + cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, &ws, NULL, 0, seed, sizeof(seed)); /* check working states V and C */ @@ -324,9 +324,9 @@ static int __init prng_sha512_selftest(void) } /* generate random bytes */ - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, + cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &ws, buf, sizeof(buf), NULL, 0); - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, + cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &ws, buf, sizeof(buf), NULL, 0); /* check against expected data */ @@ -374,16 +374,16 @@ static int __init prng_sha512_instantiate(void) /* followed by 16 bytes of unique nonce */ get_tod_clock_ext(seed + 64 + 32); - /* initial seed of the ppno drng */ - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, - &prng_data->ppnows, NULL, 0, seed, sizeof(seed)); + /* initial seed of the prno drng */ + cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, + &prng_data->prnows, NULL, 0, seed, sizeof(seed)); /* if fips mode is enabled, generate a first block of random bytes for the FIPS 140-2 Conditional Self Test */ if (fips_enabled) { prng_data->prev = prng_data->buf + prng_chunk_size; - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, - &prng_data->ppnows, + cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, + &prng_data->prnows, prng_data->prev, prng_chunk_size, NULL, 0); } @@ -412,9 +412,9 @@ static int prng_sha512_reseed(void) if (ret != sizeof(seed)) return ret; - /* do a reseed of the ppno drng with this bytestring */ - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, - &prng_data->ppnows, NULL, 0, seed, sizeof(seed)); + /* do a reseed of the prno drng with this bytestring */ + cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, + &prng_data->prnows, NULL, 0, seed, sizeof(seed)); return 0; } @@ -425,15 +425,15 @@ static int prng_sha512_generate(u8 *buf, size_t nbytes) int ret; /* reseed needed ? */ - if (prng_data->ppnows.reseed_counter > prng_reseed_limit) { + if (prng_data->prnows.reseed_counter > prng_reseed_limit) { ret = prng_sha512_reseed(); if (ret) return ret; } - /* PPNO generate */ - cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, - &prng_data->ppnows, buf, nbytes, NULL, 0); + /* PRNO generate */ + cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, + &prng_data->prnows, buf, nbytes, NULL, 0); /* FIPS 140-2 Conditional Self Test */ if (fips_enabled) { @@ -653,7 +653,7 @@ static ssize_t prng_counter_show(struct device *dev, if (mutex_lock_interruptible(&prng_data->mutex)) return -ERESTARTSYS; if (prng_mode == PRNG_MODE_SHA512) - counter = prng_data->ppnows.stream_bytes; + counter = prng_data->prnows.stream_bytes; else counter = prng_data->prngws.byte_counter; mutex_unlock(&prng_data->mutex); @@ -774,8 +774,8 @@ static int __init prng_init(void) /* choose prng mode */ if (prng_mode != PRNG_MODE_TDES) { - /* check for MSA5 support for PPNO operations */ - if (!cpacf_query_func(CPACF_PPNO, CPACF_PPNO_SHA512_DRNG_GEN)) { + /* check for MSA5 support for PRNO operations */ + if (!cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) { if (prng_mode == PRNG_MODE_SHA512) { pr_err("The prng module cannot " "start in SHA-512 mode\n"); diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 68bfd09f1b02..97189dbaf34b 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -179,7 +179,7 @@ CONFIG_FTRACE_SYSCALLS=y CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y CONFIG_STACK_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_UPROBE_EVENT=y +CONFIG_UPROBE_EVENTS=y CONFIG_FUNCTION_PROFILER=y CONFIG_TRACE_ENUM_MAP_FILE=y CONFIG_KPROBES_SANITY_TEST=y diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index 8aea32fe8bd2..7e3481eb2174 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -1,8 +1,14 @@ generic-y += asm-offsets.h generic-y += clkdev.h generic-y += dma-contiguous.h +generic-y += div64.h +generic-y += emergency-restart.h generic-y += export.h +generic-y += irq_regs.h generic-y += irq_work.h +generic-y += kmap_types.h +generic-y += local.h +generic-y += local64.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h generic-y += preempt.h diff --git a/arch/s390/include/asm/archrandom.h b/arch/s390/include/asm/archrandom.h new file mode 100644 index 000000000000..6033901a40b2 --- /dev/null +++ b/arch/s390/include/asm/archrandom.h @@ -0,0 +1,69 @@ +/* + * Kernel interface for the s390 arch_random_* functions + * + * Copyright IBM Corp. 2017 + * + * Author: Harald Freudenberger <freude@de.ibm.com> + * + */ + +#ifndef _ASM_S390_ARCHRANDOM_H +#define _ASM_S390_ARCHRANDOM_H + +#ifdef CONFIG_ARCH_RANDOM + +#include <linux/static_key.h> +#include <linux/atomic.h> +#include <asm/cpacf.h> + +DECLARE_STATIC_KEY_FALSE(s390_arch_random_available); +extern atomic64_t s390_arch_random_counter; + +static void s390_arch_random_generate(u8 *buf, unsigned int nbytes) +{ + cpacf_trng(NULL, 0, buf, nbytes); + atomic64_add(nbytes, &s390_arch_random_counter); +} + +static inline bool arch_has_random(void) +{ + if (static_branch_likely(&s390_arch_random_available)) + return true; + return false; +} + +static inline bool arch_has_random_seed(void) +{ + return arch_has_random(); +} + +static inline bool arch_get_random_long(unsigned long *v) +{ + if (static_branch_likely(&s390_arch_random_available)) { + s390_arch_random_generate((u8 *)v, sizeof(*v)); + return true; + } + return false; +} + +static inline bool arch_get_random_int(unsigned int *v) +{ + if (static_branch_likely(&s390_arch_random_available)) { + s390_arch_random_generate((u8 *)v, sizeof(*v)); + return true; + } + return false; +} + +static inline bool arch_get_random_seed_long(unsigned long *v) +{ + return arch_get_random_long(v); +} + +static inline bool arch_get_random_seed_int(unsigned int *v) +{ + return arch_get_random_int(v); +} + +#endif /* CONFIG_ARCH_RANDOM */ +#endif /* _ASM_S390_ARCHRANDOM_H */ diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h index ac9e2b939d04..ba6d29412344 100644 --- a/arch/s390/include/asm/atomic_ops.h +++ b/arch/s390/include/asm/atomic_ops.h @@ -111,20 +111,22 @@ __ATOMIC64_OPS(__atomic64_xor, "xgr") static inline int __atomic_cmpxchg(int *ptr, int old, int new) { - asm volatile( - " cs %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr) - : [new] "d" (new) : "cc", "memory"); - return old; + return __sync_val_compare_and_swap(ptr, old, new); +} + +static inline int __atomic_cmpxchg_bool(int *ptr, int old, int new) +{ + return __sync_bool_compare_and_swap(ptr, old, new); } static inline long __atomic64_cmpxchg(long *ptr, long old, long new) { - asm volatile( - " csg %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr) - : [new] "d" (new) : "cc", "memory"); - return old; + return __sync_val_compare_and_swap(ptr, old, new); +} + +static inline long __atomic64_cmpxchg_bool(long *ptr, long old, long new) +{ + return __sync_bool_compare_and_swap(ptr, old, new); } #endif /* __ARCH_S390_ATOMIC_OPS__ */ diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index d92047da5ccb..99902b7b9f0c 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -15,14 +15,6 @@ * end up numbered: * |63..............0|127............64|191...........128|255...........192| * - * There are a few little-endian macros used mostly for filesystem - * bitmaps, these work on similar bit array layouts, but byte-oriented: - * |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56| - * - * The main difference is that bit 3-5 in the bit number field needs to be - * reversed compared to the big-endian bit fields. This can be achieved by - * XOR with 0x38. - * * We also have special functions which work with an MSB0 encoding. * The bits are numbered: * |0..............63|64............127|128...........191|192...........255| @@ -253,6 +245,11 @@ unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size); unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, unsigned long offset); +#define for_each_set_bit_inv(bit, addr, size) \ + for ((bit) = find_first_bit_inv((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit_inv((addr), (size), (bit) + 1)) + static inline void set_bit_inv(unsigned long nr, volatile unsigned long *ptr) { return set_bit(nr ^ (BITS_PER_LONG - 1), ptr); diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h index bf90d1fd97a5..1bbd9dbfe4e0 100644 --- a/arch/s390/include/asm/bug.h +++ b/arch/s390/include/asm/bug.h @@ -46,8 +46,8 @@ unreachable(); \ } while (0) -#define __WARN_TAINT(taint) do { \ - __EMIT_BUG(BUGFLAG_TAINT(taint)); \ +#define __WARN_FLAGS(flags) do { \ + __EMIT_BUG(BUGFLAG_WARNING|(flags)); \ } while (0) #define WARN_ON(x) ({ \ diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index f7ed88cc066e..7a38ca85190b 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -33,6 +33,24 @@ struct ccw1 { __u32 cda; } __attribute__ ((packed,aligned(8))); +/** + * struct ccw0 - channel command word + * @cmd_code: command code + * @cda: data address + * @flags: flags, like IDA addressing, etc. + * @reserved: will be ignored + * @count: byte count + * + * The format-0 ccw structure. + */ +struct ccw0 { + __u8 cmd_code; + __u32 cda : 24; + __u8 flags; + __u8 reserved; + __u16 count; +} __packed __aligned(8); + #define CCW_FLAG_DC 0x80 #define CCW_FLAG_CC 0x40 #define CCW_FLAG_SLI 0x20 diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h index e2dfbf280d12..e06f2556b316 100644 --- a/arch/s390/include/asm/cpacf.h +++ b/arch/s390/include/asm/cpacf.h @@ -25,7 +25,8 @@ #define CPACF_KMO 0xb92b /* MSA4 */ #define CPACF_PCC 0xb92c /* MSA4 */ #define CPACF_KMCTR 0xb92d /* MSA4 */ -#define CPACF_PPNO 0xb93c /* MSA5 */ +#define CPACF_PRNO 0xb93c /* MSA5 */ +#define CPACF_KMA 0xb929 /* MSA8 */ /* * En/decryption modifier bits @@ -123,12 +124,14 @@ #define CPACF_PCKMO_ENC_AES_256_KEY 0x14 /* - * Function codes for the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) + * Function codes for the PRNO (PERFORM RANDOM NUMBER OPERATION) * instruction */ -#define CPACF_PPNO_QUERY 0x00 -#define CPACF_PPNO_SHA512_DRNG_GEN 0x03 -#define CPACF_PPNO_SHA512_DRNG_SEED 0x83 +#define CPACF_PRNO_QUERY 0x00 +#define CPACF_PRNO_SHA512_DRNG_GEN 0x03 +#define CPACF_PRNO_SHA512_DRNG_SEED 0x83 +#define CPACF_PRNO_TRNG_Q_R2C_RATIO 0x70 +#define CPACF_PRNO_TRNG 0x72 typedef struct { unsigned char bytes[16]; } cpacf_mask_t; @@ -149,8 +152,8 @@ static inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask) asm volatile( " spm 0\n" /* pckmo doesn't change the cc */ - /* Parameter registers are ignored, but may not be 0 */ - "0: .insn rrf,%[opc] << 16,2,2,2,0\n" + /* Parameter regs are ignored, but must be nonzero and unique */ + "0: .insn rrf,%[opc] << 16,2,4,6,0\n" " brc 1,0b\n" /* handle partial completion */ : "=m" (*mask) : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (opcode) @@ -173,7 +176,7 @@ static inline int __cpacf_check_opcode(unsigned int opcode) case CPACF_PCC: case CPACF_KMCTR: return test_facility(77); /* check for MSA4 */ - case CPACF_PPNO: + case CPACF_PRNO: return test_facility(57); /* check for MSA5 */ default: BUG(); @@ -373,18 +376,18 @@ static inline int cpacf_kmctr(unsigned long func, void *param, u8 *dest, } /** - * cpacf_ppno() - executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) + * cpacf_prno() - executes the PRNO (PERFORM RANDOM NUMBER OPERATION) * instruction - * @func: the function code passed to PPNO; see CPACF_PPNO_xxx defines + * @func: the function code passed to PRNO; see CPACF_PRNO_xxx defines * @param: address of parameter block; see POP for details on each func * @dest: address of destination memory area * @dest_len: size of destination memory area in bytes * @seed: address of seed data * @seed_len: size of seed data in bytes */ -static inline void cpacf_ppno(unsigned long func, void *param, - u8 *dest, long dest_len, - const u8 *seed, long seed_len) +static inline void cpacf_prno(unsigned long func, void *param, + u8 *dest, unsigned long dest_len, + const u8 *seed, unsigned long seed_len) { register unsigned long r0 asm("0") = (unsigned long) func; register unsigned long r1 asm("1") = (unsigned long) param; @@ -398,7 +401,32 @@ static inline void cpacf_ppno(unsigned long func, void *param, " brc 1,0b\n" /* handle partial completion */ : [dst] "+a" (r2), [dlen] "+d" (r3) : [fc] "d" (r0), [pba] "a" (r1), - [seed] "a" (r4), [slen] "d" (r5), [opc] "i" (CPACF_PPNO) + [seed] "a" (r4), [slen] "d" (r5), [opc] "i" (CPACF_PRNO) + : "cc", "memory"); +} + +/** + * cpacf_trng() - executes the TRNG subfunction of the PRNO instruction + * @ucbuf: buffer for unconditioned data + * @ucbuf_len: amount of unconditioned data to fetch in bytes + * @cbuf: buffer for conditioned data + * @cbuf_len: amount of conditioned data to fetch in bytes + */ +static inline void cpacf_trng(u8 *ucbuf, unsigned long ucbuf_len, + u8 *cbuf, unsigned long cbuf_len) +{ + register unsigned long r0 asm("0") = (unsigned long) CPACF_PRNO_TRNG; + register unsigned long r2 asm("2") = (unsigned long) ucbuf; + register unsigned long r3 asm("3") = (unsigned long) ucbuf_len; + register unsigned long r4 asm("4") = (unsigned long) cbuf; + register unsigned long r5 asm("5") = (unsigned long) cbuf_len; + + asm volatile ( + "0: .insn rre,%[opc] << 16,%[ucbuf],%[cbuf]\n" + " brc 1,0b\n" /* handle partial completion */ + : [ucbuf] "+a" (r2), [ucbuflen] "+d" (r3), + [cbuf] "+a" (r4), [cbuflen] "+d" (r5) + : [fc] "d" (r0), [opc] "i" (CPACF_PRNO) : "cc", "memory"); } diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index d1e0707310fd..05480e4cc5ca 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h @@ -20,9 +20,11 @@ #define CPU_MF_INT_SF_PRA (1 << 29) /* program request alert */ #define CPU_MF_INT_SF_SACA (1 << 23) /* sampler auth. change alert */ #define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */ +#define CPU_MF_INT_CF_MTDA (1 << 15) /* loss of MT ctr. data alert */ #define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */ #define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */ -#define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA) +#define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_MTDA|CPU_MF_INT_CF_CACA| \ + CPU_MF_INT_CF_LCDA) #define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \ CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \ CPU_MF_INT_SF_LSDA) @@ -172,7 +174,7 @@ static inline int lcctl(u64 ctl) /* Extract CPU counter */ static inline int __ecctr(u64 ctr, u64 *content) { - register u64 _content asm("4") = 0; + u64 _content; int cc; asm volatile ( diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index d1c407ddf703..9072bf63a846 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -8,31 +8,27 @@ #define _S390_CPUTIME_H #include <linux/types.h> -#include <asm/div64.h> +#include <asm/timex.h> #define CPUTIME_PER_USEC 4096ULL #define CPUTIME_PER_SEC (CPUTIME_PER_USEC * USEC_PER_SEC) /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ -typedef unsigned long long __nocast cputime_t; -typedef unsigned long long __nocast cputime64_t; - #define cmpxchg_cputime(ptr, old, new) cmpxchg64(ptr, old, new) -static inline unsigned long __div(unsigned long long n, unsigned long base) -{ - return n / base; -} - /* - * Convert cputime to microseconds and back. + * Convert cputime to microseconds. */ -static inline unsigned int cputime_to_usecs(const cputime_t cputime) +static inline u64 cputime_to_usecs(const u64 cputime) { - return (__force unsigned long long) cputime >> 12; + return cputime >> 12; } +/* + * Convert cputime to nanoseconds. + */ +#define cputime_to_nsecs(cputime) tod_to_ns(cputime) u64 arch_cpu_idle_time(int cpu); diff --git a/arch/s390/include/asm/div64.h b/arch/s390/include/asm/div64.h deleted file mode 100644 index 6cd978cefb28..000000000000 --- a/arch/s390/include/asm/div64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/div64.h> diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 1d48880b3cc1..e8f623041769 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -105,6 +105,7 @@ #define HWCAP_S390_VXRS 2048 #define HWCAP_S390_VXRS_BCD 4096 #define HWCAP_S390_VXRS_EXT 8192 +#define HWCAP_S390_GS 16384 /* Internal bits, not exposed via elf */ #define HWCAP_INT_SIE 1UL diff --git a/arch/s390/include/asm/emergency-restart.h b/arch/s390/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42e..000000000000 --- a/arch/s390/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include <asm-generic/emergency-restart.h> - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/s390/include/asm/extable.h b/arch/s390/include/asm/extable.h new file mode 100644 index 000000000000..16cfe2d62eeb --- /dev/null +++ b/arch/s390/include/asm/extable.h @@ -0,0 +1,28 @@ +#ifndef __S390_EXTABLE_H +#define __S390_EXTABLE_H +/* + * 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 +{ + int insn, fixup; +}; + +static inline unsigned long extable_fixup(const struct exception_table_entry *x) +{ + return (unsigned long)&x->fixup + x->fixup; +} + +#define ARCH_HAS_RELATIVE_EXTABLE + +#endif diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 09b406db7529..cb60d5c5755d 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -8,14 +8,11 @@ #define __ASM_FACILITY_H #include <generated/facilities.h> - -#ifndef __ASSEMBLY__ - #include <linux/string.h> #include <linux/preempt.h> #include <asm/lowcore.h> -#define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ +#define MAX_FACILITY_BIT (sizeof(((struct lowcore *)0)->stfle_fac_list) * 8) static inline int __test_facility(unsigned long nr, void *facilities) { @@ -72,5 +69,4 @@ static inline void stfle(u64 *stfle_fac_list, int size) preempt_enable(); } -#endif /* __ASSEMBLY__ */ #endif /* __ASM_FACILITY_H */ diff --git a/arch/s390/include/asm/irq_regs.h b/arch/s390/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b70270..000000000000 --- a/arch/s390/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/irq_regs.h> diff --git a/arch/s390/include/asm/isc.h b/arch/s390/include/asm/isc.h index 68d7d68300f2..8a0b721a9b8d 100644 --- a/arch/s390/include/asm/isc.h +++ b/arch/s390/include/asm/isc.h @@ -16,6 +16,7 @@ #define CONSOLE_ISC 1 /* console I/O subchannel */ #define EADM_SCH_ISC 4 /* EADM subchannels */ #define CHSC_SCH_ISC 7 /* CHSC subchannels */ +#define VFIO_CCW_ISC IO_SCH_ISC /* VFIO-CCW I/O subchannels */ /* Adapter interrupts. */ #define QDIO_AIRQ_ISC IO_SCH_ISC /* I/O subchannel in qdio mode */ #define PCI_ISC 2 /* PCI I/O subchannels */ diff --git a/arch/s390/include/asm/kmap_types.h b/arch/s390/include/asm/kmap_types.h deleted file mode 100644 index 0a88622339ee..000000000000 --- a/arch/s390/include/asm/kmap_types.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_KMAP_TYPES_H -#define _ASM_KMAP_TYPES_H - -#include <asm-generic/kmap_types.h> - -#endif diff --git a/arch/s390/include/asm/local.h b/arch/s390/include/asm/local.h deleted file mode 100644 index c11c530f74d0..000000000000 --- a/arch/s390/include/asm/local.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local.h> diff --git a/arch/s390/include/asm/local64.h b/arch/s390/include/asm/local64.h deleted file mode 100644 index 36c93b5cc239..000000000000 --- a/arch/s390/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local64.h> diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 61261e0e95c0..8a5b082797f8 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -157,8 +157,8 @@ struct lowcore { __u64 stfle_fac_list[32]; /* 0x0f00 */ __u8 pad_0x1000[0x11b0-0x1000]; /* 0x1000 */ - /* Pointer to vector register save area */ - __u64 vector_save_area_addr; /* 0x11b0 */ + /* Pointer to the machine check extended save area */ + __u64 mcesad; /* 0x11b0 */ /* 64 bit extparam used for pfault/diag 250: defined by architecture */ __u64 ext_params2; /* 0x11B8 */ @@ -182,10 +182,7 @@ struct lowcore { /* Transaction abort diagnostic block */ __u8 pgm_tdb[256]; /* 0x1800 */ - __u8 pad_0x1900[0x1c00-0x1900]; /* 0x1900 */ - - /* Software defined save area for vector registers */ - __u8 vector_save_area[1024]; /* 0x1c00 */ + __u8 pad_0x1900[0x2000-0x1900]; /* 0x1900 */ } __packed; #define S390_lowcore (*((struct lowcore *) 0)) diff --git a/arch/s390/include/asm/mman.h b/arch/s390/include/asm/mman.h index b55a59e1d134..b79813d9cf68 100644 --- a/arch/s390/include/asm/mman.h +++ b/arch/s390/include/asm/mman.h @@ -8,8 +8,4 @@ #include <uapi/asm/mman.h> -#ifndef __ASSEMBLY__ -int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags); -#define arch_mmap_check(addr, len, flags) s390_mmap_check(addr, len, flags) -#endif #endif /* __S390_MMAN_H__ */ diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index bea785d7f853..bd6f30304518 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h @@ -22,6 +22,8 @@ typedef struct { unsigned int has_pgste:1; /* The mmu context uses storage keys. */ unsigned int use_skey:1; + /* The mmu context uses CMMA. */ + unsigned int use_cmma:1; } mm_context_t; #define INIT_MM_CONTEXT(name) \ diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 6e31d87fb669..8712e11bead4 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -28,6 +28,7 @@ static inline int init_new_context(struct task_struct *tsk, mm->context.alloc_pgste = page_table_allocate_pgste; mm->context.has_pgste = 0; mm->context.use_skey = 0; + mm->context.use_cmma = 0; #endif switch (mm->context.asce_limit) { case 1UL << 42: @@ -156,10 +157,4 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, /* by default, allow everything */ return true; } - -static inline bool arch_pte_access_permitted(pte_t pte, bool write) -{ - /* by default, allow everything */ - return true; -} #endif /* __S390_MMU_CONTEXT_H */ diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h index b75fd910386a..e3e8895f5d3e 100644 --- a/arch/s390/include/asm/nmi.h +++ b/arch/s390/include/asm/nmi.h @@ -58,7 +58,9 @@ union mci { u64 ie : 1; /* 32 indirect storage error */ u64 ar : 1; /* 33 access register validity */ u64 da : 1; /* 34 delayed access exception */ - u64 : 7; /* 35-41 */ + u64 : 1; /* 35 */ + u64 gs : 1; /* 36 guarded storage registers */ + u64 : 5; /* 37-41 */ u64 pr : 1; /* 42 tod programmable register validity */ u64 fc : 1; /* 43 fp control register validity */ u64 ap : 1; /* 44 ancillary report */ @@ -69,6 +71,14 @@ union mci { }; }; +#define MCESA_ORIGIN_MASK (~0x3ffUL) +#define MCESA_LC_MASK (0xfUL) + +struct mcesa { + u8 vector_save_area[1024]; + u8 guarded_storage_save_area[32]; +}; + struct pt_regs; extern void s390_handle_mcck(void); diff --git a/arch/s390/include/asm/page-states.h b/arch/s390/include/asm/page-states.h new file mode 100644 index 000000000000..42267a2fe29e --- /dev/null +++ b/arch/s390/include/asm/page-states.h @@ -0,0 +1,19 @@ +/* + * Copyright IBM Corp. 2017 + * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> + */ + +#ifndef PAGE_STATES_H +#define PAGE_STATES_H + +#define ESSA_GET_STATE 0 +#define ESSA_SET_STABLE 1 +#define ESSA_SET_UNUSED 2 +#define ESSA_SET_VOLATILE 3 +#define ESSA_SET_POT_VOLATILE 4 +#define ESSA_SET_STABLE_RESIDENT 5 +#define ESSA_SET_STABLE_IF_RESIDENT 6 + +#define ESSA_MAX ESSA_SET_STABLE_IF_RESIDENT + +#endif diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index c64c0befd3f3..dd32beb9d30c 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h @@ -1,7 +1,7 @@ /* * Performance event support - s390 specific definitions. * - * Copyright IBM Corp. 2009, 2013 + * Copyright IBM Corp. 2009, 2017 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> * Hendrik Brueckner <brueckner@linux.vnet.ibm.com> */ @@ -47,7 +47,7 @@ struct perf_sf_sde_regs { }; /* Perf PMU definitions for the counter facility */ -#define PERF_CPUM_CF_MAX_CTR 256 +#define PERF_CPUM_CF_MAX_CTR 0xffffUL /* Max ctr for ECCTR */ /* Perf PMU definitions for the sampling facility */ #define PERF_CPUM_SF_MAX_CTR 2 diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 7ed1972b1920..e6e3b887bee3 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -24,6 +24,7 @@ * the S390 page table tree. */ #ifndef __ASSEMBLY__ +#include <asm-generic/5level-fixup.h> #include <linux/sched.h> #include <linux/mm_types.h> #include <linux/page-flags.h> @@ -371,10 +372,12 @@ static inline int is_module_addr(void *addr) #define PGSTE_VSIE_BIT 0x0000200000000000UL /* ref'd in a shadow table */ /* Guest Page State used for virtualization */ -#define _PGSTE_GPS_ZERO 0x0000000080000000UL -#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL -#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL -#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL +#define _PGSTE_GPS_ZERO 0x0000000080000000UL +#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL +#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL +#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL +#define _PGSTE_GPS_USAGE_POT_VOLATILE 0x0000000002000000UL +#define _PGSTE_GPS_USAGE_VOLATILE _PGSTE_GPS_USAGE_MASK /* * A user page table pointer has the space-switch-event bit, the @@ -1040,6 +1043,12 @@ int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr); int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, unsigned char *key); +int set_pgste_bits(struct mm_struct *mm, unsigned long addr, + unsigned long bits, unsigned long value); +int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep); +int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, + unsigned long *oldpte, unsigned long *oldpgste); + /* * Certain architectures need to do special things when PTEs * within a page table are directly modified. Thus, the following @@ -1050,6 +1059,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, { if (!MACHINE_HAS_NX) pte_val(entry) &= ~_PAGE_NOEXEC; + if (pte_present(entry)) + pte_val(entry) &= ~_PAGE_UNUSED; if (mm_has_pgste(mm)) ptep_set_pte_at(mm, addr, ptep, entry); else diff --git a/arch/s390/include/asm/pkey.h b/arch/s390/include/asm/pkey.h index b48aef4188f6..4c484590d858 100644 --- a/arch/s390/include/asm/pkey.h +++ b/arch/s390/include/asm/pkey.h @@ -87,4 +87,25 @@ int pkey_findcard(const struct pkey_seckey *seckey, int pkey_skey2pkey(const struct pkey_seckey *seckey, struct pkey_protkey *protkey); +/* + * Verify the given secure key for being able to be useable with + * the pkey module. Check for correct key type and check for having at + * least one crypto card being able to handle this key (master key + * or old master key verification pattern matches). + * Return some info about the key: keysize in bits, keytype (currently + * only AES), flag if key is wrapped with an old MKVP. + * @param seckey pointer to buffer with the input secure key + * @param pcardnr pointer to cardnr, receives the card number on success + * @param pdomain pointer to domain, receives the domain number on success + * @param pkeysize pointer to keysize, receives the bitsize of the key + * @param pattributes pointer to attributes, receives additional info + * PKEY_VERIFY_ATTR_AES if the key is an AES key + * PKEY_VERIFY_ATTR_OLD_MKVP if key has old mkvp stored in + * @return 0 on success, negative errno value on failure. If no card could + * be found which is able to handle this key, -ENODEV is returned. + */ +int pkey_verifykey(const struct pkey_seckey *seckey, + u16 *pcardnr, u16 *pdomain, + u16 *pkeysize, u32 *pattributes); + #endif /* _KAPI_PKEY_H */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index e4988710aa86..60d395fdc864 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -91,14 +91,15 @@ extern void execve_tail(void); * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. */ -#define TASK_SIZE_OF(tsk) ((tsk)->mm ? \ - (tsk)->mm->context.asce_limit : TASK_MAX_SIZE) +#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_31BIT) ? \ + (1UL << 31) : (1UL << 53)) #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ (1UL << 30) : (1UL << 41)) #define TASK_SIZE TASK_SIZE_OF(current) -#define TASK_MAX_SIZE (1UL << 53) +#define TASK_SIZE_MAX (1UL << 53) -#define STACK_TOP (1UL << (test_thread_flag(TIF_31BIT) ? 31:42)) +#define STACK_TOP (test_thread_flag(TIF_31BIT) ? \ + (1UL << 31) : (1UL << 42)) #define STACK_TOP_MAX (1UL << 42) #define HAVE_ARCH_PICK_MMAP_LAYOUT @@ -135,6 +136,8 @@ struct thread_struct { struct list_head list; /* cpu runtime instrumentation */ struct runtime_instr_cb *ri_cb; + struct gs_cb *gs_cb; /* Current guarded storage cb */ + struct gs_cb *gs_bc_cb; /* Broadcast guarded storage cb */ unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ /* * Warning: 'fpu' is dynamically-sized. It *MUST* be at @@ -215,6 +218,9 @@ void show_cacheinfo(struct seq_file *m); /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); +/* Free guarded storage control block for current */ +void exit_thread_gs(void); + /* * Return saved PC of a blocked thread. */ diff --git a/arch/s390/include/asm/sections.h b/arch/s390/include/asm/sections.h index 5ce29fe100ba..fbd9116eb17b 100644 --- a/arch/s390/include/asm/sections.h +++ b/arch/s390/include/asm/sections.h @@ -4,6 +4,5 @@ #include <asm-generic/sections.h> extern char _eshared[], _ehead[]; -extern char __start_ro_after_init[], __end_ro_after_init[]; #endif diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 30bdb5a027f3..cd78155b1829 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -29,8 +29,8 @@ #define MACHINE_FLAG_TE _BITUL(11) #define MACHINE_FLAG_TLB_LC _BITUL(12) #define MACHINE_FLAG_VX _BITUL(13) -#define MACHINE_FLAG_CAD _BITUL(14) -#define MACHINE_FLAG_NX _BITUL(15) +#define MACHINE_FLAG_NX _BITUL(14) +#define MACHINE_FLAG_GS _BITUL(15) #define LPP_MAGIC _BITUL(31) #define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL) @@ -68,8 +68,8 @@ extern void detect_memory_memblock(void); #define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC) #define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX) -#define MACHINE_HAS_CAD (S390_lowcore.machine_flags & MACHINE_FLAG_CAD) #define MACHINE_HAS_NX (S390_lowcore.machine_flags & MACHINE_FLAG_NX) +#define MACHINE_HAS_GS (S390_lowcore.machine_flags & MACHINE_FLAG_GS) /* * Console mode. Override with conmode= diff --git a/arch/s390/include/asm/sparsemem.h b/arch/s390/include/asm/sparsemem.h index 487428b6d099..334e279f1bce 100644 --- a/arch/s390/include/asm/sparsemem.h +++ b/arch/s390/include/asm/sparsemem.h @@ -2,6 +2,6 @@ #define _ASM_S390_SPARSEMEM_H #define SECTION_SIZE_BITS 28 -#define MAX_PHYSMEM_BITS 46 +#define MAX_PHYSMEM_BITS CONFIG_MAX_PHYSMEM_BITS #endif /* _ASM_S390_SPARSEMEM_H */ diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h index ffc45048ea7d..f7838ecd83c6 100644 --- a/arch/s390/include/asm/spinlock.h +++ b/arch/s390/include/asm/spinlock.h @@ -10,6 +10,7 @@ #define __ASM_SPINLOCK_H #include <linux/smp.h> +#include <asm/atomic_ops.h> #include <asm/barrier.h> #include <asm/processor.h> @@ -17,12 +18,6 @@ extern int spin_retry; -static inline int -_raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new) -{ - return __sync_bool_compare_and_swap(lock, old, new); -} - #ifndef CONFIG_SMP static inline bool arch_vcpu_is_preempted(int cpu) { return false; } #else @@ -40,7 +35,7 @@ bool arch_vcpu_is_preempted(int cpu); * (the type definitions are in asm/spinlock_types.h) */ -void arch_lock_relax(unsigned int cpu); +void arch_lock_relax(int cpu); void arch_spin_lock_wait(arch_spinlock_t *); int arch_spin_trylock_retry(arch_spinlock_t *); @@ -70,7 +65,7 @@ static inline int arch_spin_trylock_once(arch_spinlock_t *lp) { barrier(); return likely(arch_spin_value_unlocked(*lp) && - _raw_compare_and_swap(&lp->lock, 0, SPINLOCK_LOCKVAL)); + __atomic_cmpxchg_bool(&lp->lock, 0, SPINLOCK_LOCKVAL)); } static inline void arch_spin_lock(arch_spinlock_t *lp) @@ -95,7 +90,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lp) static inline void arch_spin_unlock(arch_spinlock_t *lp) { - typecheck(unsigned int, lp->lock); + typecheck(int, lp->lock); asm volatile( "st %1,%0\n" : "+Q" (lp->lock) @@ -141,16 +136,16 @@ extern int _raw_write_trylock_retry(arch_rwlock_t *lp); static inline int arch_read_trylock_once(arch_rwlock_t *rw) { - unsigned int old = ACCESS_ONCE(rw->lock); - return likely((int) old >= 0 && - _raw_compare_and_swap(&rw->lock, old, old + 1)); + int old = ACCESS_ONCE(rw->lock); + return likely(old >= 0 && + __atomic_cmpxchg_bool(&rw->lock, old, old + 1)); } static inline int arch_write_trylock_once(arch_rwlock_t *rw) { - unsigned int old = ACCESS_ONCE(rw->lock); + int old = ACCESS_ONCE(rw->lock); return likely(old == 0 && - _raw_compare_and_swap(&rw->lock, 0, 0x80000000)); + __atomic_cmpxchg_bool(&rw->lock, 0, 0x80000000)); } #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES @@ -161,9 +156,9 @@ static inline int arch_write_trylock_once(arch_rwlock_t *rw) #define __RAW_LOCK(ptr, op_val, op_string) \ ({ \ - unsigned int old_val; \ + int old_val; \ \ - typecheck(unsigned int *, ptr); \ + typecheck(int *, ptr); \ asm volatile( \ op_string " %0,%2,%1\n" \ "bcr 14,0\n" \ @@ -175,9 +170,9 @@ static inline int arch_write_trylock_once(arch_rwlock_t *rw) #define __RAW_UNLOCK(ptr, op_val, op_string) \ ({ \ - unsigned int old_val; \ + int old_val; \ \ - typecheck(unsigned int *, ptr); \ + typecheck(int *, ptr); \ asm volatile( \ op_string " %0,%2,%1\n" \ : "=d" (old_val), "+Q" (*ptr) \ @@ -187,14 +182,14 @@ static inline int arch_write_trylock_once(arch_rwlock_t *rw) }) extern void _raw_read_lock_wait(arch_rwlock_t *lp); -extern void _raw_write_lock_wait(arch_rwlock_t *lp, unsigned int prev); +extern void _raw_write_lock_wait(arch_rwlock_t *lp, int prev); static inline void arch_read_lock(arch_rwlock_t *rw) { - unsigned int old; + int old; old = __RAW_LOCK(&rw->lock, 1, __RAW_OP_ADD); - if ((int) old < 0) + if (old < 0) _raw_read_lock_wait(rw); } @@ -205,7 +200,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) static inline void arch_write_lock(arch_rwlock_t *rw) { - unsigned int old; + int old; old = __RAW_LOCK(&rw->lock, 0x80000000, __RAW_OP_OR); if (old != 0) @@ -232,11 +227,11 @@ static inline void arch_read_lock(arch_rwlock_t *rw) static inline void arch_read_unlock(arch_rwlock_t *rw) { - unsigned int old; + int old; do { old = ACCESS_ONCE(rw->lock); - } while (!_raw_compare_and_swap(&rw->lock, old, old - 1)); + } while (!__atomic_cmpxchg_bool(&rw->lock, old, old - 1)); } static inline void arch_write_lock(arch_rwlock_t *rw) @@ -248,7 +243,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw) static inline void arch_write_unlock(arch_rwlock_t *rw) { - typecheck(unsigned int, rw->lock); + typecheck(int, rw->lock); rw->owner = 0; asm volatile( diff --git a/arch/s390/include/asm/spinlock_types.h b/arch/s390/include/asm/spinlock_types.h index d84b6939237c..fe755eec275f 100644 --- a/arch/s390/include/asm/spinlock_types.h +++ b/arch/s390/include/asm/spinlock_types.h @@ -6,14 +6,14 @@ #endif typedef struct { - unsigned int lock; + int lock; } __attribute__ ((aligned (4))) arch_spinlock_t; #define __ARCH_SPIN_LOCK_UNLOCKED { .lock = 0, } typedef struct { - unsigned int lock; - unsigned int owner; + int lock; + int owner; } arch_rwlock_t; #define __ARCH_RW_LOCK_UNLOCKED { 0 } diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h index 12d45f0cfdd9..f6c2b5814ab0 100644 --- a/arch/s390/include/asm/switch_to.h +++ b/arch/s390/include/asm/switch_to.h @@ -10,6 +10,7 @@ #include <linux/thread_info.h> #include <asm/fpu/api.h> #include <asm/ptrace.h> +#include <asm/guarded_storage.h> extern struct task_struct *__switch_to(void *, void *); extern void update_cr_regs(struct task_struct *task); @@ -33,12 +34,14 @@ static inline void restore_access_regs(unsigned int *acrs) save_fpu_regs(); \ save_access_regs(&prev->thread.acrs[0]); \ save_ri_cb(prev->thread.ri_cb); \ + save_gs_cb(prev->thread.gs_cb); \ } \ if (next->mm) { \ update_cr_regs(next); \ set_cpu_flag(CIF_FPU); \ restore_access_regs(&next->thread.acrs[0]); \ restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ + restore_gs_cb(next->thread.gs_cb); \ } \ prev = __switch_to(prev,next); \ } while (0) diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index 229326c942c7..73bff45ced55 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h @@ -142,7 +142,15 @@ struct sysinfo_3_2_2 { extern int topology_max_mnest; -#define TOPOLOGY_CORE_BITS 64 +/* + * Returns the maximum nesting level supported by the cpu topology code. + * The current maximum level is 4 which is the drawer level. + */ +static inline int topology_mnest_limit(void) +{ + return min(topology_max_mnest, 4); +} + #define TOPOLOGY_NR_MAG 6 struct topology_core { @@ -152,7 +160,7 @@ struct topology_core { unsigned char pp:2; unsigned char reserved1; unsigned short origin; - unsigned long mask[TOPOLOGY_CORE_BITS / BITS_PER_LONG]; + unsigned long mask; }; struct topology_container { diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 646845edf148..0b3ee083a665 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -56,7 +56,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); #define TIF_SIGPENDING 1 /* signal pending */ #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_UPROBE 3 /* breakpointed or single-stepping */ -#define TIF_PATCH_PENDING 4 /* pending live patching update */ +#define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */ +#define TIF_PATCH_PENDING 5 /* pending live patching update */ #define TIF_31BIT 16 /* 32bit process */ #define TIF_MEMDIE 17 /* is terminating due to OOM killer */ @@ -75,6 +76,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); #define _TIF_SIGPENDING _BITUL(TIF_SIGPENDING) #define _TIF_NEED_RESCHED _BITUL(TIF_NEED_RESCHED) #define _TIF_UPROBE _BITUL(TIF_UPROBE) +#define _TIF_GUARDED_STORAGE _BITUL(TIF_GUARDED_STORAGE) #define _TIF_PATCH_PENDING _BITUL(TIF_PATCH_PENDING) #define _TIF_31BIT _BITUL(TIF_31BIT) diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 354344dcc198..118535123f34 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -206,20 +206,16 @@ static inline unsigned long long get_tod_clock_monotonic(void) * ns = (todval * 125) >> 9; * * In order to avoid an overflow with the multiplication we can rewrite this. - * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) + * With a split todval == 2^9 * th + tl (th upper 55 bits, tl lower 9 bits) * we end up with * - * ns = ((2^32 * th + tl) * 125 ) >> 9; - * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); + * ns = ((2^9 * th + tl) * 125 ) >> 9; + * -> ns = (th * 125) + ((tl * 125) >> 9); * */ static inline unsigned long long tod_to_ns(unsigned long long todval) { - unsigned long long ns; - - ns = ((todval >> 32) << 23) * 125; - ns += ((todval & 0xffffffff) * 125) >> 9; - return ns; + return ((todval >> 9) * 125) + (((todval & 0x1ff) * 125) >> 9); } #endif diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 136932ff4250..78f3f093d143 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -12,13 +12,9 @@ /* * User space memory access functions */ -#include <linux/sched.h> -#include <linux/errno.h> #include <asm/processor.h> #include <asm/ctl_reg.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 +#include <asm/extable.h> /* @@ -42,7 +38,7 @@ static inline void set_fs(mm_segment_t fs) { current->thread.mm_segment = fs; - if (segment_eq(fs, KERNEL_DS)) { + if (uaccess_kernel()) { set_cpu_flag(CIF_ASCE_SECONDARY); __ctl_load(S390_lowcore.kernel_asce, 7, 7); } else { @@ -64,72 +60,14 @@ static inline int __range_ok(unsigned long addr, unsigned long size) #define access_ok(type, addr, size) __access_ok(addr, size) -/* - * 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 -{ - int insn, fixup; -}; - -static inline unsigned long extable_fixup(const struct exception_table_entry *x) -{ - return (unsigned long)&x->fixup + x->fixup; -} - -#define ARCH_HAS_RELATIVE_EXTABLE - -/** - * __copy_from_user: - Copy a block of data from user space, with less checking. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -unsigned long __must_check __copy_from_user(void *to, const void __user *from, - unsigned long n); +unsigned long __must_check +raw_copy_from_user(void *to, const void __user *from, unsigned long n); -/** - * __copy_to_user: - Copy a block of data into user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -unsigned long __must_check __copy_to_user(void __user *to, const void *from, - unsigned long n); +unsigned long __must_check +raw_copy_to_user(void __user *to, const void *from, unsigned long n); -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES @@ -147,7 +85,7 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from, " jg 2b\n" \ ".popsection\n" \ EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ - : "=d" (__rc), "=Q" (*(to)) \ + : "=d" (__rc), "+Q" (*(to)) \ : "d" (size), "Q" (*(from)), \ "d" (__reg0), "K" (-EFAULT) \ : "cc"); \ @@ -218,13 +156,13 @@ static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long s static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) { - size = __copy_to_user(ptr, x, size); + size = raw_copy_to_user(ptr, x, size); return size ? -EFAULT : 0; } static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) { - size = __copy_from_user(x, ptr, size); + size = raw_copy_from_user(x, ptr, size); return size ? -EFAULT : 0; } @@ -314,77 +252,8 @@ int __get_user_bad(void) __attribute__((noreturn)); #define __put_user_unaligned __put_user #define __get_user_unaligned __get_user -extern void __compiletime_error("usercopy buffer size is too small") -__bad_copy_user(void); - -static inline void copy_user_overflow(int size, unsigned long count) -{ - WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); -} - -/** - * copy_to_user: - Copy a block of data into user space. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -static inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - might_fault(); - return __copy_to_user(to, from, n); -} - -/** - * copy_from_user: - Copy a block of data from user space. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -static inline unsigned long __must_check -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - unsigned int sz = __compiletime_object_size(to); - - might_fault(); - if (unlikely(sz != -1 && sz < n)) { - if (!__builtin_constant_p(n)) - copy_user_overflow(sz, n); - else - __bad_copy_user(); - return n; - } - return __copy_from_user(to, from, n); -} - unsigned long __must_check -__copy_in_user(void __user *to, const void __user *from, unsigned long n); - -static inline unsigned long __must_check -copy_in_user(void __user *to, const void __user *from, unsigned long n) -{ - might_fault(); - return __copy_in_user(to, from, n); -} +raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); /* * Copy a null terminated string from userspace. diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild index 6848ba5c1454..addb09cee0f5 100644 --- a/arch/s390/include/uapi/asm/Kbuild +++ b/arch/s390/include/uapi/asm/Kbuild @@ -1,6 +1,16 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +generic-y += errno.h +generic-y += fcntl.h +generic-y += ioctl.h +generic-y += mman.h +generic-y += param.h +generic-y += poll.h +generic-y += resource.h +generic-y += sockios.h +generic-y += termbits.h + header-y += auxvec.h header-y += bitsperlong.h header-y += byteorder.h @@ -11,25 +21,20 @@ header-y += cmb.h header-y += dasd.h header-y += debug.h header-y += errno.h -header-y += fcntl.h +header-y += guarded_storage.h header-y += hypfs.h -header-y += ioctl.h header-y += ioctls.h header-y += ipcbuf.h header-y += kvm.h header-y += kvm_para.h header-y += kvm_perf.h header-y += kvm_virtio.h -header-y += mman.h header-y += monwriter.h header-y += msgbuf.h -header-y += param.h header-y += pkey.h -header-y += poll.h header-y += posix_types.h header-y += ptrace.h header-y += qeth.h -header-y += resource.h header-y += schid.h header-y += sclp_ctl.h header-y += sembuf.h @@ -40,12 +45,10 @@ header-y += sigcontext.h header-y += siginfo.h header-y += signal.h header-y += socket.h -header-y += sockios.h header-y += stat.h header-y += statfs.h header-y += swab.h header-y += tape390.h -header-y += termbits.h header-y += termios.h header-y += types.h header-y += ucontext.h diff --git a/arch/s390/include/uapi/asm/errno.h b/arch/s390/include/uapi/asm/errno.h deleted file mode 100644 index 395e97d8005e..000000000000 --- a/arch/s390/include/uapi/asm/errno.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * S390 version - * - */ - -#ifndef _S390_ERRNO_H -#define _S390_ERRNO_H - -#include <asm-generic/errno.h> - -#endif diff --git a/arch/s390/include/uapi/asm/fcntl.h b/arch/s390/include/uapi/asm/fcntl.h deleted file mode 100644 index 46ab12db5739..000000000000 --- a/arch/s390/include/uapi/asm/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/fcntl.h> diff --git a/arch/s390/include/uapi/asm/guarded_storage.h b/arch/s390/include/uapi/asm/guarded_storage.h new file mode 100644 index 000000000000..852850e8e17e --- /dev/null +++ b/arch/s390/include/uapi/asm/guarded_storage.h @@ -0,0 +1,77 @@ +#ifndef _GUARDED_STORAGE_H +#define _GUARDED_STORAGE_H + +#include <linux/types.h> + +struct gs_cb { + __u64 reserved; + __u64 gsd; + __u64 gssm; + __u64 gs_epl_a; +}; + +struct gs_epl { + __u8 pad1; + union { + __u8 gs_eam; + struct { + __u8 : 6; + __u8 e : 1; + __u8 b : 1; + }; + }; + union { + __u8 gs_eci; + struct { + __u8 tx : 1; + __u8 cx : 1; + __u8 : 5; + __u8 in : 1; + }; + }; + union { + __u8 gs_eai; + struct { + __u8 : 1; + __u8 t : 1; + __u8 as : 2; + __u8 ar : 4; + }; + }; + __u32 pad2; + __u64 gs_eha; + __u64 gs_eia; + __u64 gs_eoa; + __u64 gs_eir; + __u64 gs_era; +}; + +#define GS_ENABLE 0 +#define GS_DISABLE 1 +#define GS_SET_BC_CB 2 +#define GS_CLEAR_BC_CB 3 +#define GS_BROADCAST 4 + +static inline void load_gs_cb(struct gs_cb *gs_cb) +{ + asm volatile(".insn rxy,0xe3000000004d,0,%0" : : "Q" (*gs_cb)); +} + +static inline void store_gs_cb(struct gs_cb *gs_cb) +{ + asm volatile(".insn rxy,0xe30000000049,0,%0" : : "Q" (*gs_cb)); +} + +static inline void save_gs_cb(struct gs_cb *gs_cb) +{ + if (gs_cb) + store_gs_cb(gs_cb); +} + +static inline void restore_gs_cb(struct gs_cb *gs_cb) +{ + if (gs_cb) + load_gs_cb(gs_cb); +} + +#endif /* _GUARDED_STORAGE_H */ diff --git a/arch/s390/include/uapi/asm/ioctl.h b/arch/s390/include/uapi/asm/ioctl.h deleted file mode 100644 index b279fe06dfe5..000000000000 --- a/arch/s390/include/uapi/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ioctl.h> diff --git a/arch/s390/include/uapi/asm/mman.h b/arch/s390/include/uapi/asm/mman.h deleted file mode 100644 index de23da1f41b2..000000000000 --- a/arch/s390/include/uapi/asm/mman.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * S390 version - * - * Derived from "include/asm-i386/mman.h" - */ -#include <asm-generic/mman.h> diff --git a/arch/s390/include/uapi/asm/param.h b/arch/s390/include/uapi/asm/param.h deleted file mode 100644 index c616821bf2ac..000000000000 --- a/arch/s390/include/uapi/asm/param.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASMS390_PARAM_H -#define _ASMS390_PARAM_H - -#include <asm-generic/param.h> - -#endif /* _ASMS390_PARAM_H */ diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h index ed7f19c27ce5..e6c04faf8a6c 100644 --- a/arch/s390/include/uapi/asm/pkey.h +++ b/arch/s390/include/uapi/asm/pkey.h @@ -109,4 +109,23 @@ struct pkey_skey2pkey { }; #define PKEY_SKEY2PKEY _IOWR(PKEY_IOCTL_MAGIC, 0x06, struct pkey_skey2pkey) +/* + * Verify the given secure key for being able to be useable with + * the pkey module. Check for correct key type and check for having at + * least one crypto card being able to handle this key (master key + * or old master key verification pattern matches). + * Return some info about the key: keysize in bits, keytype (currently + * only AES), flag if key is wrapped with an old MKVP. + */ +struct pkey_verifykey { + struct pkey_seckey seckey; /* in: the secure key blob */ + __u16 cardnr; /* out: card number */ + __u16 domain; /* out: domain number */ + __u16 keysize; /* out: key size in bits */ + __u32 attributes; /* out: attribute bits */ +}; +#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey) +#define PKEY_VERIFY_ATTR_AES 0x00000001 /* key is an AES key */ +#define PKEY_VERIFY_ATTR_OLD_MKVP 0x00000100 /* key has old MKVP value */ + #endif /* _UAPI_PKEY_H */ diff --git a/arch/s390/include/uapi/asm/poll.h b/arch/s390/include/uapi/asm/poll.h deleted file mode 100644 index c98509d3149e..000000000000 --- a/arch/s390/include/uapi/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/poll.h> diff --git a/arch/s390/include/uapi/asm/resource.h b/arch/s390/include/uapi/asm/resource.h deleted file mode 100644 index ec23d1c73c92..000000000000 --- a/arch/s390/include/uapi/asm/resource.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * S390 version - * - * Derived from "include/asm-i386/resources.h" - */ - -#ifndef _S390_RESOURCE_H -#define _S390_RESOURCE_H - -#include <asm-generic/resource.h> - -#endif - diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h index b24a64cbfeb1..e8e5ecf673fd 100644 --- a/arch/s390/include/uapi/asm/socket.h +++ b/arch/s390/include/uapi/asm/socket.h @@ -98,4 +98,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/s390/include/uapi/asm/sockios.h b/arch/s390/include/uapi/asm/sockios.h deleted file mode 100644 index 6f60eee73242..000000000000 --- a/arch/s390/include/uapi/asm/sockios.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_S390_SOCKIOS_H -#define _ASM_S390_SOCKIOS_H - -#include <asm-generic/sockios.h> - -#endif diff --git a/arch/s390/include/uapi/asm/termbits.h b/arch/s390/include/uapi/asm/termbits.h deleted file mode 100644 index 71bf6ac6a2b9..000000000000 --- a/arch/s390/include/uapi/asm/termbits.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_S390_TERMBITS_H -#define _ASM_S390_TERMBITS_H - -#include <asm-generic/termbits.h> - -#endif diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index 4384bc797a54..ea42290e7d51 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h @@ -313,7 +313,9 @@ #define __NR_copy_file_range 375 #define __NR_preadv2 376 #define __NR_pwritev2 377 -#define NR_syscalls 378 +#define __NR_s390_guarded_storage 378 +#define __NR_statx 379 +#define NR_syscalls 380 /* * There are some system calls that are not present on 64 bit, some diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 060ce548fe8b..adb3fe2e3d42 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -51,14 +51,12 @@ CFLAGS_dumpstack.o += -fno-optimize-sibling-calls # CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' -CFLAGS_sysinfo.o += -w - obj-y := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o -obj-y += runtime_instr.o cache.o fpu.o dumpstack.o -obj-y += entry.o reipl.o relocate_kernel.o +obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o +obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o extra-y += head.o head64.o vmlinux.lds diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index c4b3570ded5b..6bb29633e1f1 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -175,7 +175,7 @@ int main(void) /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ OFFSET(__LC_DUMP_REIPL, lowcore, ipib); /* hardware defined lowcore locations 0x1000 - 0x18ff */ - OFFSET(__LC_VX_SAVE_AREA_ADDR, lowcore, vector_save_area_addr); + OFFSET(__LC_MCESAD, lowcore, mcesad); OFFSET(__LC_EXT_PARAMS2, lowcore, ext_params2); OFFSET(__LC_FPREGS_SAVE_AREA, lowcore, floating_pt_save_area); OFFSET(__LC_GPREGS_SAVE_AREA, lowcore, gpregs_save_area); diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c index ae2cda5eee5a..986642a3543b 100644 --- a/arch/s390/kernel/compat_wrapper.c +++ b/arch/s390/kernel/compat_wrapper.c @@ -178,3 +178,5 @@ COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len); COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags); COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags); +COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb); +COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer); diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index dd1d5c62c374..d628afc26708 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -429,6 +429,20 @@ static void *nt_vmcoreinfo(void *ptr) } /* + * Initialize final note (needed for /proc/vmcore code) + */ +static void *nt_final(void *ptr) +{ + Elf64_Nhdr *note; + + note = (Elf64_Nhdr *) ptr; + note->n_namesz = 0; + note->n_descsz = 0; + note->n_type = 0; + return PTR_ADD(ptr, sizeof(Elf64_Nhdr)); +} + +/* * Initialize ELF header (new kernel) */ static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt) @@ -515,6 +529,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) if (sa->prefix != 0) ptr = fill_cpu_elf_notes(ptr, cpu++, sa); ptr = nt_vmcoreinfo(ptr); + ptr = nt_final(ptr); memset(phdr, 0, sizeof(*phdr)); phdr->p_type = PT_NOTE; phdr->p_offset = notes_offset; diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 4e65c79cc5f2..5d20182ee8ae 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -231,9 +231,29 @@ static noinline __init void detect_machine_type(void) S390_lowcore.machine_flags |= MACHINE_FLAG_VM; } +/* Remove leading, trailing and double whitespace. */ +static inline void strim_all(char *str) +{ + char *s; + + s = strim(str); + if (s != str) + memmove(str, s, strlen(s)); + while (*str) { + if (!isspace(*str++)) + continue; + if (isspace(*str)) { + s = skip_spaces(str); + memmove(str, s, strlen(s) + 1); + } + } +} + static noinline __init void setup_arch_string(void) { struct sysinfo_1_1_1 *mach = (struct sysinfo_1_1_1 *)&sysinfo_page; + struct sysinfo_3_2_2 *vm = (struct sysinfo_3_2_2 *)&sysinfo_page; + char mstr[80], hvstr[17]; if (stsi(mach, 1, 1, 1)) return; @@ -241,14 +261,21 @@ static noinline __init void setup_arch_string(void) EBCASC(mach->type, sizeof(mach->type)); EBCASC(mach->model, sizeof(mach->model)); EBCASC(mach->model_capacity, sizeof(mach->model_capacity)); - dump_stack_set_arch_desc("%-16.16s %-4.4s %-16.16s %-16.16s (%s)", - mach->manufacturer, - mach->type, - mach->model, - mach->model_capacity, - MACHINE_IS_LPAR ? "LPAR" : - MACHINE_IS_VM ? "z/VM" : - MACHINE_IS_KVM ? "KVM" : "unknown"); + sprintf(mstr, "%-16.16s %-4.4s %-16.16s %-16.16s", + mach->manufacturer, mach->type, + mach->model, mach->model_capacity); + strim_all(mstr); + if (stsi(vm, 3, 2, 2) == 0 && vm->count) { + EBCASC(vm->vm[0].cpi, sizeof(vm->vm[0].cpi)); + sprintf(hvstr, "%-16.16s", vm->vm[0].cpi); + strim_all(hvstr); + } else { + sprintf(hvstr, "%s", + MACHINE_IS_LPAR ? "LPAR" : + MACHINE_IS_VM ? "z/VM" : + MACHINE_IS_KVM ? "KVM" : "unknown"); + } + dump_stack_set_arch_desc("%s (%s)", mstr, hvstr); } static __init void setup_topology(void) @@ -358,6 +385,8 @@ static __init void detect_machine_facilities(void) S390_lowcore.machine_flags |= MACHINE_FLAG_NX; __ctl_set_bit(0, 20); } + if (test_facility(133)) + S390_lowcore.machine_flags |= MACHINE_FLAG_GS; } static inline void save_vector_registers(void) @@ -375,7 +404,7 @@ static int __init topology_setup(char *str) rc = kstrtobool(str, &enabled); if (!rc && !enabled) - S390_lowcore.machine_flags &= ~MACHINE_HAS_TOPOLOGY; + S390_lowcore.machine_flags &= ~MACHINE_FLAG_TOPOLOGY; return rc; } early_param("topology", topology_setup); @@ -405,23 +434,16 @@ early_param("noexec", noexec_setup); static int __init cad_setup(char *str) { - int val; - - get_option(&str, &val); - if (val && test_facility(128)) - S390_lowcore.machine_flags |= MACHINE_FLAG_CAD; - return 0; -} -early_param("cad", cad_setup); + bool enabled; + int rc; -static int __init cad_init(void) -{ - if (MACHINE_HAS_CAD) + rc = kstrtobool(str, &enabled); + if (!rc && enabled && test_facility(128)) /* Enable problem state CAD. */ __ctl_set_bit(2, 3); - return 0; + return rc; } -early_initcall(cad_init); +early_param("cad", cad_setup); static __init void memmove_early(void *dst, const void *src, size_t n) { diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index a08b5eea5567..a5f5d3bb3dbc 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -47,7 +47,7 @@ STACK_SIZE = 1 << STACK_SHIFT STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE _TIF_WORK = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ - _TIF_UPROBE | _TIF_PATCH_PENDING) + _TIF_UPROBE | _TIF_GUARDED_STORAGE | _TIF_PATCH_PENDING) _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ _TIF_SYSCALL_TRACEPOINT) _CIF_WORK = (_CIF_MCCK_PENDING | _CIF_ASCE_PRIMARY | \ @@ -189,8 +189,6 @@ ENTRY(__switch_to) stg %r3,__LC_CURRENT # store task struct of next stg %r15,__LC_KERNEL_STACK # store end of kernel stack lg %r15,__THREAD_ksp(%r1) # load kernel stack of next - /* c4 is used in guest detection: arch/s390/kernel/perf_cpum_sf.c */ - lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP @@ -332,6 +330,8 @@ ENTRY(system_call) TSTMSK __TI_flags(%r12),_TIF_UPROBE jo .Lsysc_uprobe_notify #endif + TSTMSK __TI_flags(%r12),_TIF_GUARDED_STORAGE + jo .Lsysc_guarded_storage TSTMSK __PT_FLAGS(%r11),_PIF_PER_TRAP jo .Lsysc_singlestep #ifdef CONFIG_LIVEPATCH @@ -414,6 +414,13 @@ ENTRY(system_call) #endif # +# _TIF_GUARDED_STORAGE is set, call guarded_storage_load +# +.Lsysc_guarded_storage: + lgr %r2,%r11 # pass pointer to pt_regs + larl %r14,.Lsysc_return + jg gs_load_bc_cb +# # _TIF_PATCH_PENDING is set, call klp_update_patch_state # #ifdef CONFIG_LIVEPATCH @@ -505,7 +512,7 @@ ENTRY(pgm_check_handler) jnz .Lpgm_svcper # -> single stepped svc 1: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) - j 3f + j 4f 2: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER lg %r15,__LC_KERNEL_STACK lgr %r14,%r12 @@ -514,8 +521,8 @@ ENTRY(pgm_check_handler) tm __LC_PGM_ILC+2,0x02 # check for transaction abort jz 3f mvc __THREAD_trap_tdb(256,%r14),0(%r13) -3: la %r11,STACK_FRAME_OVERHEAD(%r15) - stg %r10,__THREAD_last_break(%r14) +3: stg %r10,__THREAD_last_break(%r14) +4: la %r11,STACK_FRAME_OVERHEAD(%r15) stmg %r0,%r7,__PT_R0(%r11) mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC stmg %r8,%r9,__PT_PSW(%r11) @@ -524,14 +531,14 @@ ENTRY(pgm_check_handler) xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) stg %r10,__PT_ARGS(%r11) tm __LC_PGM_ILC+3,0x80 # check for per exception - jz 4f + jz 5f tmhh %r8,0x0001 # kernel per event ? jz .Lpgm_kprobe oi __PT_FLAGS+7(%r11),_PIF_PER_TRAP mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS mvc __THREAD_per_cause(2,%r14),__LC_PER_CODE mvc __THREAD_per_paid(1,%r14),__LC_PER_ACCESS_ID -4: REENABLE_IRQS +5: REENABLE_IRQS xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) larl %r1,pgm_check_table llgh %r10,__PT_INT_CODE+2(%r11) @@ -682,6 +689,8 @@ ENTRY(io_int_handler) jo .Lio_sigpending TSTMSK __TI_flags(%r12),_TIF_NOTIFY_RESUME jo .Lio_notify_resume + TSTMSK __TI_flags(%r12),_TIF_GUARDED_STORAGE + jo .Lio_guarded_storage TSTMSK __LC_CPU_FLAGS,_CIF_FPU jo .Lio_vxrs TSTMSK __LC_CPU_FLAGS,(_CIF_ASCE_PRIMARY|_CIF_ASCE_SECONDARY) @@ -716,6 +725,18 @@ ENTRY(io_int_handler) jg load_fpu_regs # +# _TIF_GUARDED_STORAGE is set, call guarded_storage_load +# +.Lio_guarded_storage: + # TRACE_IRQS_ON already done at .Lio_return + ssm __LC_SVC_NEW_PSW # reenable interrupts + lgr %r2,%r11 # pass pointer to pt_regs + brasl %r14,gs_load_bc_cb + ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts + TRACE_IRQS_OFF + j .Lio_return + +# # _TIF_NEED_RESCHED is set, call schedule # .Lio_reschedule: diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index 33f901865326..dbf5f7e18246 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -74,12 +74,14 @@ long sys_sigreturn(void); long sys_s390_personality(unsigned int personality); long sys_s390_runtime_instr(int command, int signum); +long sys_s390_guarded_storage(int command, struct gs_cb __user *); long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t); long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); DECLARE_PER_CPU(u64, mt_cycles[8]); void verify_facilities(void); +void gs_load_bc_cb(struct pt_regs *regs); void set_fs_fixup(void); #endif /* _ENTRY_H */ diff --git a/arch/s390/kernel/guarded_storage.c b/arch/s390/kernel/guarded_storage.c new file mode 100644 index 000000000000..6f064745c3b1 --- /dev/null +++ b/arch/s390/kernel/guarded_storage.c @@ -0,0 +1,128 @@ +/* + * Copyright IBM Corp. 2016 + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#include <linux/kernel.h> +#include <linux/syscalls.h> +#include <linux/signal.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <asm/guarded_storage.h> +#include "entry.h" + +void exit_thread_gs(void) +{ + kfree(current->thread.gs_cb); + kfree(current->thread.gs_bc_cb); + current->thread.gs_cb = current->thread.gs_bc_cb = NULL; +} + +static int gs_enable(void) +{ + struct gs_cb *gs_cb; + + if (!current->thread.gs_cb) { + gs_cb = kzalloc(sizeof(*gs_cb), GFP_KERNEL); + if (!gs_cb) + return -ENOMEM; + gs_cb->gsd = 25; + preempt_disable(); + __ctl_set_bit(2, 4); + load_gs_cb(gs_cb); + current->thread.gs_cb = gs_cb; + preempt_enable(); + } + return 0; +} + +static int gs_disable(void) +{ + if (current->thread.gs_cb) { + preempt_disable(); + kfree(current->thread.gs_cb); + current->thread.gs_cb = NULL; + __ctl_clear_bit(2, 4); + preempt_enable(); + } + return 0; +} + +static int gs_set_bc_cb(struct gs_cb __user *u_gs_cb) +{ + struct gs_cb *gs_cb; + + gs_cb = current->thread.gs_bc_cb; + if (!gs_cb) { + gs_cb = kzalloc(sizeof(*gs_cb), GFP_KERNEL); + if (!gs_cb) + return -ENOMEM; + current->thread.gs_bc_cb = gs_cb; + } + if (copy_from_user(gs_cb, u_gs_cb, sizeof(*gs_cb))) + return -EFAULT; + return 0; +} + +static int gs_clear_bc_cb(void) +{ + struct gs_cb *gs_cb; + + gs_cb = current->thread.gs_bc_cb; + current->thread.gs_bc_cb = NULL; + kfree(gs_cb); + return 0; +} + +void gs_load_bc_cb(struct pt_regs *regs) +{ + struct gs_cb *gs_cb; + + preempt_disable(); + clear_thread_flag(TIF_GUARDED_STORAGE); + gs_cb = current->thread.gs_bc_cb; + if (gs_cb) { + kfree(current->thread.gs_cb); + current->thread.gs_bc_cb = NULL; + __ctl_set_bit(2, 4); + load_gs_cb(gs_cb); + current->thread.gs_cb = gs_cb; + } + preempt_enable(); +} + +static int gs_broadcast(void) +{ + struct task_struct *sibling; + + read_lock(&tasklist_lock); + for_each_thread(current, sibling) { + if (!sibling->thread.gs_bc_cb) + continue; + if (test_and_set_tsk_thread_flag(sibling, TIF_GUARDED_STORAGE)) + kick_process(sibling); + } + read_unlock(&tasklist_lock); + return 0; +} + +SYSCALL_DEFINE2(s390_guarded_storage, int, command, + struct gs_cb __user *, gs_cb) +{ + if (!MACHINE_HAS_GS) + return -EOPNOTSUPP; + switch (command) { + case GS_ENABLE: + return gs_enable(); + case GS_DISABLE: + return gs_disable(); + case GS_SET_BC_CB: + return gs_set_bc_cb(gs_cb); + case GS_CLEAR_BC_CB: + return gs_clear_bc_cb(); + case GS_BROADCAST: + return gs_broadcast(); + default: + return -EINVAL; + } +} diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 0b5ebf8a3d30..eff5b31671d4 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -25,7 +25,6 @@ #include <linux/linkage.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> -#include <asm/facility.h> #include <asm/page.h> #include <asm/ptrace.h> diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 482d3526e32b..31c91f24e562 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -52,7 +52,7 @@ ENTRY(startup_continue) .quad 0 # cr1: primary space segment table .quad .Lduct # cr2: dispatchable unit control table .quad 0 # cr3: instruction authorization - .quad 0 # cr4: instruction authorization + .quad 0xffff # cr4: instruction authorization .quad .Lduct # cr5: primary-aste origin .quad 0 # cr6: I/O interrupts .quad 0 # cr7: secondary space segment table diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index b67dafb7b7cf..e545ffe5155a 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -564,6 +564,8 @@ static struct kset *ipl_kset; static void __ipl_run(void *unused) { + if (MACHINE_IS_LPAR && ipl_info.type == IPL_TYPE_CCW) + diag308(DIAG308_LOAD_NORMAL_DUMP, NULL); diag308(DIAG308_LOAD_CLEAR, NULL); if (MACHINE_IS_VM) __cpcmd("IPL", NULL, 0, NULL); diff --git a/arch/s390/kernel/kdebugfs.c b/arch/s390/kernel/kdebugfs.c new file mode 100644 index 000000000000..ee85e17dd79d --- /dev/null +++ b/arch/s390/kernel/kdebugfs.c @@ -0,0 +1,15 @@ +#include <linux/debugfs.h> +#include <linux/export.h> +#include <linux/init.h> + +struct dentry *arch_debugfs_dir; +EXPORT_SYMBOL(arch_debugfs_dir); + +static int __init arch_kdebugfs_init(void) +{ + arch_debugfs_dir = debugfs_create_dir("s390", NULL); + if (IS_ERR(arch_debugfs_dir)) + arch_debugfs_dir = NULL; + return 0; +} +postcore_initcall(arch_kdebugfs_init); diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 3074c1d83829..db5658daf994 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -27,6 +27,7 @@ #include <asm/cacheflush.h> #include <asm/os_info.h> #include <asm/switch_to.h> +#include <asm/nmi.h> typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long); @@ -102,6 +103,8 @@ static void __do_machine_kdump(void *image) */ static noinline void __machine_kdump(void *image) { + struct mcesa *mcesa; + unsigned long cr2_old, cr2_new; int this_cpu, cpu; lgr_info_log(); @@ -114,8 +117,16 @@ static noinline void __machine_kdump(void *image) continue; } /* Store status of the boot CPU */ + mcesa = (struct mcesa *)(S390_lowcore.mcesad & MCESA_ORIGIN_MASK); if (MACHINE_HAS_VX) - save_vx_regs((void *) &S390_lowcore.vector_save_area); + save_vx_regs((__vector128 *) mcesa->vector_save_area); + if (MACHINE_HAS_GS) { + __ctl_store(cr2_old, 2, 2); + cr2_new = cr2_old | (1UL << 4); + __ctl_load(cr2_new, 2, 2); + save_gs_cb((struct gs_cb *) mcesa->guarded_storage_save_area); + __ctl_load(cr2_old, 2, 2); + } /* * To create a good backchain for this CPU in the dump store_status * is passed the address of a function. The address is saved into diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 9bf8327154ee..985589523970 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -106,6 +106,7 @@ static int notrace s390_validate_registers(union mci mci, int umode) int kill_task; u64 zero; void *fpt_save_area; + struct mcesa *mcesa; kill_task = 0; zero = 0; @@ -165,6 +166,7 @@ static int notrace s390_validate_registers(union mci mci, int umode) : : "Q" (S390_lowcore.fpt_creg_save_area)); } + mcesa = (struct mcesa *)(S390_lowcore.mcesad & MCESA_ORIGIN_MASK); if (!MACHINE_HAS_VX) { /* Validate floating point registers */ asm volatile( @@ -209,8 +211,8 @@ static int notrace s390_validate_registers(union mci mci, int umode) " la 1,%0\n" " .word 0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */ " .word 0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */ - : : "Q" (*(struct vx_array *) - &S390_lowcore.vector_save_area) : "1"); + : : "Q" (*(struct vx_array *) mcesa->vector_save_area) + : "1"); __ctl_load(S390_lowcore.cregs_save_area[0], 0, 0); } /* Validate access registers */ @@ -224,6 +226,19 @@ static int notrace s390_validate_registers(union mci mci, int umode) */ kill_task = 1; } + /* Validate guarded storage registers */ + if (MACHINE_HAS_GS && (S390_lowcore.cregs_save_area[2] & (1UL << 4))) { + if (!mci.gs) + /* + * Guarded storage register can't be restored and + * the current processes uses guarded storage. + * It has to be terminated. + */ + kill_task = 1; + else + load_gs_cb((struct gs_cb *) + mcesa->guarded_storage_save_area); + } /* * We don't even try to validate the TOD register, since we simply * can't write something sensible into that register. diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 1aba10e90906..746d03423333 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -1,7 +1,7 @@ /* * Performance event support for s390x - CPU-measurement Counter Facility * - * Copyright IBM Corp. 2012 + * Copyright IBM Corp. 2012, 2017 * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> * * This program is free software; you can redistribute it and/or modify @@ -22,19 +22,12 @@ #include <asm/irq.h> #include <asm/cpu_mf.h> -/* CPU-measurement counter facility supports these CPU counter sets: - * For CPU counter sets: - * Basic counter set: 0-31 - * Problem-state counter set: 32-63 - * Crypto-activity counter set: 64-127 - * Extented counter set: 128-159 - */ enum cpumf_ctr_set { - /* CPU counter sets */ - CPUMF_CTR_SET_BASIC = 0, - CPUMF_CTR_SET_USER = 1, - CPUMF_CTR_SET_CRYPTO = 2, - CPUMF_CTR_SET_EXT = 3, + CPUMF_CTR_SET_BASIC = 0, /* Basic Counter Set */ + CPUMF_CTR_SET_USER = 1, /* Problem-State Counter Set */ + CPUMF_CTR_SET_CRYPTO = 2, /* Crypto-Activity Counter Set */ + CPUMF_CTR_SET_EXT = 3, /* Extended Counter Set */ + CPUMF_CTR_SET_MT_DIAG = 4, /* MT-diagnostic Counter Set */ /* Maximum number of counter sets */ CPUMF_CTR_SET_MAX, @@ -47,6 +40,7 @@ static const u64 cpumf_state_ctl[CPUMF_CTR_SET_MAX] = { [CPUMF_CTR_SET_USER] = 0x04, [CPUMF_CTR_SET_CRYPTO] = 0x08, [CPUMF_CTR_SET_EXT] = 0x01, + [CPUMF_CTR_SET_MT_DIAG] = 0x20, }; static void ctr_set_enable(u64 *state, int ctr_set) @@ -76,19 +70,20 @@ struct cpu_hw_events { }; static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .ctr_set = { - [CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0), - [CPUMF_CTR_SET_USER] = ATOMIC_INIT(0), - [CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0), - [CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0), + [CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0), + [CPUMF_CTR_SET_USER] = ATOMIC_INIT(0), + [CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0), + [CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0), + [CPUMF_CTR_SET_MT_DIAG] = ATOMIC_INIT(0), }, .state = 0, .flags = 0, .txn_flags = 0, }; -static int get_counter_set(u64 event) +static enum cpumf_ctr_set get_counter_set(u64 event) { - int set = -1; + int set = CPUMF_CTR_SET_MAX; if (event < 32) set = CPUMF_CTR_SET_BASIC; @@ -98,34 +93,17 @@ static int get_counter_set(u64 event) set = CPUMF_CTR_SET_CRYPTO; else if (event < 256) set = CPUMF_CTR_SET_EXT; + else if (event >= 448 && event < 496) + set = CPUMF_CTR_SET_MT_DIAG; return set; } -static int validate_event(const struct hw_perf_event *hwc) -{ - switch (hwc->config_base) { - case CPUMF_CTR_SET_BASIC: - case CPUMF_CTR_SET_USER: - case CPUMF_CTR_SET_CRYPTO: - case CPUMF_CTR_SET_EXT: - /* check for reserved counters */ - if ((hwc->config >= 6 && hwc->config <= 31) || - (hwc->config >= 38 && hwc->config <= 63) || - (hwc->config >= 80 && hwc->config <= 127)) - return -EOPNOTSUPP; - break; - default: - return -EINVAL; - } - - return 0; -} - static int validate_ctr_version(const struct hw_perf_event *hwc) { struct cpu_hw_events *cpuhw; int err = 0; + u16 mtdiag_ctl; cpuhw = &get_cpu_var(cpu_hw_events); @@ -145,6 +123,27 @@ static int validate_ctr_version(const struct hw_perf_event *hwc) (cpuhw->info.csvn > 2 && hwc->config > 255)) err = -EOPNOTSUPP; break; + case CPUMF_CTR_SET_MT_DIAG: + if (cpuhw->info.csvn <= 3) + err = -EOPNOTSUPP; + /* + * MT-diagnostic counters are read-only. The counter set + * is automatically enabled and activated on all CPUs with + * multithreading (SMT). Deactivation of multithreading + * also disables the counter set. State changes are ignored + * by lcctl(). Because Linux controls SMT enablement through + * a kernel parameter only, the counter set is either disabled + * or enabled and active. + * + * Thus, the counters can only be used if SMT is on and the + * counter set is enabled and active. + */ + mtdiag_ctl = cpumf_state_ctl[CPUMF_CTR_SET_MT_DIAG]; + if (!((cpuhw->info.auth_ctl & mtdiag_ctl) && + (cpuhw->info.enable_ctl & mtdiag_ctl) && + (cpuhw->info.act_ctl & mtdiag_ctl))) + err = -EOPNOTSUPP; + break; } put_cpu_var(cpu_hw_events); @@ -250,6 +249,11 @@ static void cpumf_measurement_alert(struct ext_code ext_code, /* loss of counter data alert */ if (alert & CPU_MF_INT_CF_LCDA) pr_err("CPU[%i] Counter data was lost\n", smp_processor_id()); + + /* loss of MT counter data alert */ + if (alert & CPU_MF_INT_CF_MTDA) + pr_warn("CPU[%i] MT counter data was lost\n", + smp_processor_id()); } #define PMC_INIT 0 @@ -330,6 +334,7 @@ static int __hw_perf_event_init(struct perf_event *event) { struct perf_event_attr *attr = &event->attr; struct hw_perf_event *hwc = &event->hw; + enum cpumf_ctr_set set; int err; u64 ev; @@ -370,25 +375,30 @@ static int __hw_perf_event_init(struct perf_event *event) if (ev == -1) return -ENOENT; - if (ev >= PERF_CPUM_CF_MAX_CTR) + if (ev > PERF_CPUM_CF_MAX_CTR) return -EINVAL; - /* Use the hardware perf event structure to store the counter number - * in 'config' member and the counter set to which the counter belongs - * in the 'config_base'. The counter set (config_base) is then used - * to enable/disable the counters. - */ - hwc->config = ev; - hwc->config_base = get_counter_set(ev); - - /* Validate the counter that is assigned to this event. - * Because the counter facility can use numerous counters at the - * same time without constraints, it is not necessary to explicitly - * validate event groups (event->group_leader != event). - */ - err = validate_event(hwc); - if (err) - return err; + /* Obtain the counter set to which the specified counter belongs */ + set = get_counter_set(ev); + switch (set) { + case CPUMF_CTR_SET_BASIC: + case CPUMF_CTR_SET_USER: + case CPUMF_CTR_SET_CRYPTO: + case CPUMF_CTR_SET_EXT: + case CPUMF_CTR_SET_MT_DIAG: + /* + * Use the hardware perf event structure to store the + * counter number in the 'config' member and the counter + * set number in the 'config_base'. The counter set number + * is then later used to enable/disable the counter(s). + */ + hwc->config = ev; + hwc->config_base = set; + break; + case CPUMF_CTR_SET_MAX: + /* The counter could not be associated to a counter set */ + return -EINVAL; + }; /* Initialize for using the CPU-measurement counter facility */ if (!atomic_inc_not_zero(&num_events)) { @@ -452,7 +462,7 @@ static int hw_perf_event_reset(struct perf_event *event) return err; } -static int hw_perf_event_update(struct perf_event *event) +static void hw_perf_event_update(struct perf_event *event) { u64 prev, new, delta; int err; @@ -461,14 +471,12 @@ static int hw_perf_event_update(struct perf_event *event) prev = local64_read(&event->hw.prev_count); err = ecctr(event->hw.config, &new); if (err) - goto out; + return; } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev); delta = (prev <= new) ? new - prev : (-1ULL - prev) + new + 1; /* overflow */ local64_add(delta, &event->count); -out: - return err; } static void cpumf_pmu_read(struct perf_event *event) diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c index c343ac2cf6c5..d3133285b7d1 100644 --- a/arch/s390/kernel/perf_cpum_cf_events.c +++ b/arch/s390/kernel/perf_cpum_cf_events.c @@ -114,8 +114,64 @@ CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV, 0x00a1); CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TABORT, 0x00b1); CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_NO_SPECIAL, 0x00b2); CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_SPECIAL, 0x00b3); +CPUMF_EVENT_ATTR(cf_z13, L1D_WRITES_RO_EXCL, 0x0080); +CPUMF_EVENT_ATTR(cf_z13, DTLB1_WRITES, 0x0081); +CPUMF_EVENT_ATTR(cf_z13, DTLB1_MISSES, 0x0082); +CPUMF_EVENT_ATTR(cf_z13, DTLB1_HPAGE_WRITES, 0x0083); +CPUMF_EVENT_ATTR(cf_z13, DTLB1_GPAGE_WRITES, 0x0084); +CPUMF_EVENT_ATTR(cf_z13, L1D_L2D_SOURCED_WRITES, 0x0085); +CPUMF_EVENT_ATTR(cf_z13, ITLB1_WRITES, 0x0086); +CPUMF_EVENT_ATTR(cf_z13, ITLB1_MISSES, 0x0087); +CPUMF_EVENT_ATTR(cf_z13, L1I_L2I_SOURCED_WRITES, 0x0088); +CPUMF_EVENT_ATTR(cf_z13, TLB2_PTE_WRITES, 0x0089); +CPUMF_EVENT_ATTR(cf_z13, TLB2_CRSTE_HPAGE_WRITES, 0x008a); +CPUMF_EVENT_ATTR(cf_z13, TLB2_CRSTE_WRITES, 0x008b); +CPUMF_EVENT_ATTR(cf_z13, TX_C_TEND, 0x008c); +CPUMF_EVENT_ATTR(cf_z13, TX_NC_TEND, 0x008d); +CPUMF_EVENT_ATTR(cf_z13, L1C_TLB1_MISSES, 0x008f); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0090); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONCHIP_L3_SOURCED_WRITES_IV, 0x0091); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONNODE_L4_SOURCED_WRITES, 0x0092); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONNODE_L3_SOURCED_WRITES_IV, 0x0093); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONNODE_L3_SOURCED_WRITES, 0x0094); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONDRAWER_L4_SOURCED_WRITES, 0x0095); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONDRAWER_L3_SOURCED_WRITES_IV, 0x0096); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONDRAWER_L3_SOURCED_WRITES, 0x0097); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_SCOL_L4_SOURCED_WRITES, 0x0098); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV, 0x0099); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES, 0x009a); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_FCOL_L4_SOURCED_WRITES, 0x009b); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV, 0x009c); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES, 0x009d); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONNODE_MEM_SOURCED_WRITES, 0x009e); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONDRAWER_MEM_SOURCED_WRITES, 0x009f); +CPUMF_EVENT_ATTR(cf_z13, L1D_OFFDRAWER_MEM_SOURCED_WRITES, 0x00a0); +CPUMF_EVENT_ATTR(cf_z13, L1D_ONCHIP_MEM_SOURCED_WRITES, 0x00a1); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONCHIP_L3_SOURCED_WRITES, 0x00a2); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONCHIP_L3_SOURCED_WRITES_IV, 0x00a3); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONNODE_L4_SOURCED_WRITES, 0x00a4); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONNODE_L3_SOURCED_WRITES_IV, 0x00a5); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONNODE_L3_SOURCED_WRITES, 0x00a6); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONDRAWER_L4_SOURCED_WRITES, 0x00a7); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONDRAWER_L3_SOURCED_WRITES_IV, 0x00a8); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONDRAWER_L3_SOURCED_WRITES, 0x00a9); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_SCOL_L4_SOURCED_WRITES, 0x00aa); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV, 0x00ab); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES, 0x00ac); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_FCOL_L4_SOURCED_WRITES, 0x00ad); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV, 0x00ae); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES, 0x00af); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONNODE_MEM_SOURCED_WRITES, 0x00b0); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONDRAWER_MEM_SOURCED_WRITES, 0x00b1); +CPUMF_EVENT_ATTR(cf_z13, L1I_OFFDRAWER_MEM_SOURCED_WRITES, 0x00b2); +CPUMF_EVENT_ATTR(cf_z13, L1I_ONCHIP_MEM_SOURCED_WRITES, 0x00b3); +CPUMF_EVENT_ATTR(cf_z13, TX_NC_TABORT, 0x00da); +CPUMF_EVENT_ATTR(cf_z13, TX_C_TABORT_NO_SPECIAL, 0x00db); +CPUMF_EVENT_ATTR(cf_z13, TX_C_TABORT_SPECIAL, 0x00dc); +CPUMF_EVENT_ATTR(cf_z13, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0); +CPUMF_EVENT_ATTR(cf_z13, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1); -static struct attribute *cpumcf_pmu_event_attr[] = { +static struct attribute *cpumcf_pmu_event_attr[] __initdata = { CPUMF_EVENT_PTR(cf, CPU_CYCLES), CPUMF_EVENT_PTR(cf, INSTRUCTIONS), CPUMF_EVENT_PTR(cf, L1I_DIR_WRITES), @@ -236,28 +292,87 @@ static struct attribute *cpumcf_zec12_pmu_event_attr[] __initdata = { NULL, }; +static struct attribute *cpumcf_z13_pmu_event_attr[] __initdata = { + CPUMF_EVENT_PTR(cf_z13, L1D_WRITES_RO_EXCL), + CPUMF_EVENT_PTR(cf_z13, DTLB1_WRITES), + CPUMF_EVENT_PTR(cf_z13, DTLB1_MISSES), + CPUMF_EVENT_PTR(cf_z13, DTLB1_HPAGE_WRITES), + CPUMF_EVENT_PTR(cf_z13, DTLB1_GPAGE_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_L2D_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, ITLB1_WRITES), + CPUMF_EVENT_PTR(cf_z13, ITLB1_MISSES), + CPUMF_EVENT_PTR(cf_z13, L1I_L2I_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, TLB2_PTE_WRITES), + CPUMF_EVENT_PTR(cf_z13, TLB2_CRSTE_HPAGE_WRITES), + CPUMF_EVENT_PTR(cf_z13, TLB2_CRSTE_WRITES), + CPUMF_EVENT_PTR(cf_z13, TX_C_TEND), + CPUMF_EVENT_PTR(cf_z13, TX_NC_TEND), + CPUMF_EVENT_PTR(cf_z13, L1C_TLB1_MISSES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONCHIP_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONCHIP_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1D_ONNODE_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONNODE_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1D_ONNODE_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONDRAWER_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONDRAWER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1D_ONDRAWER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_SCOL_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_FCOL_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONNODE_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONDRAWER_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_OFFDRAWER_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1D_ONCHIP_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONCHIP_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONCHIP_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1I_ONNODE_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONNODE_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1I_ONNODE_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONDRAWER_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONDRAWER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1I_ONDRAWER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_SCOL_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_FCOL_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONNODE_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONDRAWER_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_OFFDRAWER_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, L1I_ONCHIP_MEM_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z13, TX_NC_TABORT), + CPUMF_EVENT_PTR(cf_z13, TX_C_TABORT_NO_SPECIAL), + CPUMF_EVENT_PTR(cf_z13, TX_C_TABORT_SPECIAL), + CPUMF_EVENT_PTR(cf_z13, MT_DIAG_CYCLES_ONE_THR_ACTIVE), + CPUMF_EVENT_PTR(cf_z13, MT_DIAG_CYCLES_TWO_THR_ACTIVE), + NULL, +}; + /* END: CPUM_CF COUNTER DEFINITIONS ===================================== */ -static struct attribute_group cpumsf_pmu_events_group = { +static struct attribute_group cpumcf_pmu_events_group = { .name = "events", - .attrs = cpumcf_pmu_event_attr, }; PMU_FORMAT_ATTR(event, "config:0-63"); -static struct attribute *cpumsf_pmu_format_attr[] = { +static struct attribute *cpumcf_pmu_format_attr[] = { &format_attr_event.attr, NULL, }; -static struct attribute_group cpumsf_pmu_format_group = { +static struct attribute_group cpumcf_pmu_format_group = { .name = "format", - .attrs = cpumsf_pmu_format_attr, + .attrs = cpumcf_pmu_format_attr, }; -static const struct attribute_group *cpumsf_pmu_attr_groups[] = { - &cpumsf_pmu_events_group, - &cpumsf_pmu_format_group, +static const struct attribute_group *cpumcf_pmu_attr_groups[] = { + &cpumcf_pmu_events_group, + &cpumcf_pmu_format_group, NULL, }; @@ -290,6 +405,7 @@ static __init struct attribute **merge_attr(struct attribute **a, __init const struct attribute_group **cpumf_cf_event_group(void) { struct attribute **combined, **model; + struct attribute *none[] = { NULL }; struct cpuid cpu_id; get_cpu_id(&cpu_id); @@ -306,17 +422,17 @@ __init const struct attribute_group **cpumf_cf_event_group(void) case 0x2828: model = cpumcf_zec12_pmu_event_attr; break; + case 0x2964: + case 0x2965: + model = cpumcf_z13_pmu_event_attr; + break; default: - model = NULL; + model = none; break; } - if (!model) - goto out; - combined = merge_attr(cpumcf_pmu_event_attr, model); if (combined) - cpumsf_pmu_events_group.attrs = combined; -out: - return cpumsf_pmu_attr_groups; + cpumcf_pmu_events_group.attrs = combined; + return cpumcf_pmu_attr_groups; } diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index 1c0b58545c04..9a4f279d25ca 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -1009,8 +1009,8 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr) * sample. Some early samples or samples from guests without * lpp usage would be misaccounted to the host. We use the asn * value as an addon heuristic to detect most of these guest samples. - * If the value differs from the host hpp value, we assume to be a - * KVM guest. + * If the value differs from 0xffff (the host value), we assume to + * be a KVM guest. */ switch (sfr->basic.CL) { case 1: /* logical partition */ @@ -1020,8 +1020,7 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr) sde_regs->in_guest = 1; break; default: /* old machine, use heuristics */ - if (sfr->basic.gpp || - sfr->basic.prim_asn != (u16)sfr->basic.hpp) + if (sfr->basic.gpp || sfr->basic.prim_asn != 0xffff) sde_regs->in_guest = 1; break; } diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 20cd339e11ae..999d7154bbdc 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -73,8 +73,10 @@ extern void kernel_thread_starter(void); */ void exit_thread(struct task_struct *tsk) { - if (tsk == current) + if (tsk == current) { exit_thread_runtime_instr(); + exit_thread_gs(); + } } void flush_thread(void) @@ -124,7 +126,10 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long new_stackp, clear_tsk_thread_flag(p, TIF_SINGLE_STEP); /* Initialize per thread user and system timer values */ p->thread.user_timer = 0; + p->thread.guest_timer = 0; p->thread.system_timer = 0; + p->thread.hardirq_timer = 0; + p->thread.softirq_timer = 0; frame->sf.back_chain = 0; /* new return point is ret_from_fork */ @@ -156,6 +161,9 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long new_stackp, /* Don't copy runtime instrumentation info */ p->thread.ri_cb = NULL; frame->childregs.psw.mask &= ~PSW_MASK_RI; + /* Don't copy guarded storage control block */ + p->thread.gs_cb = NULL; + p->thread.gs_bc_cb = NULL; /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) { diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 928b929a6261..778cd6536175 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -7,6 +7,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/cpufeature.h> +#include <linux/bitops.h> #include <linux/kernel.h> #include <linux/sched/mm.h> #include <linux/init.h> @@ -91,11 +92,23 @@ int cpu_have_feature(unsigned int num) } EXPORT_SYMBOL(cpu_have_feature); +static void show_facilities(struct seq_file *m) +{ + unsigned int bit; + long *facilities; + + facilities = (long *)&S390_lowcore.stfle_fac_list; + seq_puts(m, "facilities :"); + for_each_set_bit_inv(bit, facilities, MAX_FACILITY_BIT) + seq_printf(m, " %d", bit); + seq_putc(m, '\n'); +} + static void show_cpu_summary(struct seq_file *m, void *v) { static const char *hwcap_str[] = { "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", - "edat", "etf3eh", "highgprs", "te", "vx", "vxd", "vxe" + "edat", "etf3eh", "highgprs", "te", "vx", "vxd", "vxe", "gs" }; static const char * const int_hwcap_str[] = { "sie" @@ -116,6 +129,7 @@ static void show_cpu_summary(struct seq_file *m, void *v) if (int_hwcap_str[i] && (int_hwcap & (1UL << i))) seq_printf(m, "%s ", int_hwcap_str[i]); seq_puts(m, "\n"); + show_facilities(m); show_cacheinfo(m); for_each_online_cpu(cpu) { struct cpuid *id = &per_cpu(cpu_info.cpu_id, cpu); diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index c14df0a1ec3c..488c5bb8dc77 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -44,30 +44,42 @@ void update_cr_regs(struct task_struct *task) struct pt_regs *regs = task_pt_regs(task); struct thread_struct *thread = &task->thread; struct per_regs old, new; - + unsigned long cr0_old, cr0_new; + unsigned long cr2_old, cr2_new; + int cr0_changed, cr2_changed; + + __ctl_store(cr0_old, 0, 0); + __ctl_store(cr2_old, 2, 2); + cr0_new = cr0_old; + cr2_new = cr2_old; /* Take care of the enable/disable of transactional execution. */ if (MACHINE_HAS_TE) { - unsigned long cr, cr_new; - - __ctl_store(cr, 0, 0); /* Set or clear transaction execution TXC bit 8. */ - cr_new = cr | (1UL << 55); + cr0_new |= (1UL << 55); if (task->thread.per_flags & PER_FLAG_NO_TE) - cr_new &= ~(1UL << 55); - if (cr_new != cr) - __ctl_load(cr_new, 0, 0); + cr0_new &= ~(1UL << 55); /* Set or clear transaction execution TDC bits 62 and 63. */ - __ctl_store(cr, 2, 2); - cr_new = cr & ~3UL; + cr2_new &= ~3UL; if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) { if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND) - cr_new |= 1UL; + cr2_new |= 1UL; else - cr_new |= 2UL; + cr2_new |= 2UL; } - if (cr_new != cr) - __ctl_load(cr_new, 2, 2); } + /* Take care of enable/disable of guarded storage. */ + if (MACHINE_HAS_GS) { + cr2_new &= ~(1UL << 4); + if (task->thread.gs_cb) + cr2_new |= (1UL << 4); + } + /* Load control register 0/2 iff changed */ + cr0_changed = cr0_new != cr0_old; + cr2_changed = cr2_new != cr2_old; + if (cr0_changed) + __ctl_load(cr0_new, 0, 0); + if (cr2_changed) + __ctl_load(cr2_new, 2, 2); /* Copy user specified PER registers */ new.control = thread->per_user.control; new.start = thread->per_user.start; @@ -1137,6 +1149,74 @@ static int s390_system_call_set(struct task_struct *target, data, 0, sizeof(unsigned int)); } +static int s390_gs_cb_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + struct gs_cb *data = target->thread.gs_cb; + + if (!MACHINE_HAS_GS) + return -ENODEV; + if (!data) + return -ENODATA; + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + data, 0, sizeof(struct gs_cb)); +} + +static int s390_gs_cb_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + struct gs_cb *data = target->thread.gs_cb; + + if (!MACHINE_HAS_GS) + return -ENODEV; + if (!data) { + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + target->thread.gs_cb = data; + } + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + data, 0, sizeof(struct gs_cb)); +} + +static int s390_gs_bc_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + struct gs_cb *data = target->thread.gs_bc_cb; + + if (!MACHINE_HAS_GS) + return -ENODEV; + if (!data) + return -ENODATA; + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + data, 0, sizeof(struct gs_cb)); +} + +static int s390_gs_bc_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + struct gs_cb *data = target->thread.gs_bc_cb; + + if (!MACHINE_HAS_GS) + return -ENODEV; + if (!data) { + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + target->thread.gs_bc_cb = data; + } + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + data, 0, sizeof(struct gs_cb)); +} + static const struct user_regset s390_regsets[] = { { .core_note_type = NT_PRSTATUS, @@ -1194,6 +1274,22 @@ static const struct user_regset s390_regsets[] = { .get = s390_vxrs_high_get, .set = s390_vxrs_high_set, }, + { + .core_note_type = NT_S390_GS_CB, + .n = sizeof(struct gs_cb) / sizeof(__u64), + .size = sizeof(__u64), + .align = sizeof(__u64), + .get = s390_gs_cb_get, + .set = s390_gs_cb_set, + }, + { + .core_note_type = NT_S390_GS_BC, + .n = sizeof(struct gs_cb) / sizeof(__u64), + .size = sizeof(__u64), + .align = sizeof(__u64), + .get = s390_gs_bc_get, + .set = s390_gs_bc_set, + }, }; static const struct user_regset_view user_s390_view = { @@ -1422,6 +1518,14 @@ static const struct user_regset s390_compat_regsets[] = { .get = s390_compat_regs_high_get, .set = s390_compat_regs_high_set, }, + { + .core_note_type = NT_S390_GS_CB, + .n = sizeof(struct gs_cb) / sizeof(__u64), + .size = sizeof(__u64), + .align = sizeof(__u64), + .get = s390_gs_cb_get, + .set = s390_gs_cb_set, + }, }; static const struct user_regset_view user_s390_compat_view = { diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 911dc0b49be0..3ae756c0db3d 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -339,9 +339,15 @@ static void __init setup_lowcore(void) lc->stfl_fac_list = S390_lowcore.stfl_fac_list; memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, MAX_FACILITY_BIT/8); - if (MACHINE_HAS_VX) - lc->vector_save_area_addr = - (unsigned long) &lc->vector_save_area; + if (MACHINE_HAS_VX || MACHINE_HAS_GS) { + unsigned long bits, size; + + bits = MACHINE_HAS_GS ? 11 : 10; + size = 1UL << bits; + lc->mcesad = (__u64) memblock_virt_alloc(size, size); + if (MACHINE_HAS_GS) + lc->mcesad |= bits; + } lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; lc->sync_enter_timer = S390_lowcore.sync_enter_timer; lc->async_enter_timer = S390_lowcore.async_enter_timer; @@ -779,6 +785,12 @@ static int __init setup_hwcaps(void) elf_hwcap |= HWCAP_S390_VXRS_BCD; } + /* + * Guarded storage support HWCAP_S390_GS is bit 12. + */ + if (MACHINE_HAS_GS) + elf_hwcap |= HWCAP_S390_GS; + get_cpu_id(&cpu_id); add_device_randomness(&cpu_id, sizeof(cpu_id)); switch (cpu_id.machine) { diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 47a973b5b4f1..363000a77ffc 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -51,6 +51,7 @@ #include <asm/os_info.h> #include <asm/sigp.h> #include <asm/idle.h> +#include <asm/nmi.h> #include "entry.h" enum { @@ -78,6 +79,8 @@ struct pcpu { static u8 boot_core_type; static struct pcpu pcpu_devices[NR_CPUS]; +static struct kmem_cache *pcpu_mcesa_cache; + unsigned int smp_cpu_mt_shift; EXPORT_SYMBOL(smp_cpu_mt_shift); @@ -188,8 +191,10 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) { unsigned long async_stack, panic_stack; + unsigned long mcesa_origin, mcesa_bits; struct lowcore *lc; + mcesa_origin = mcesa_bits = 0; if (pcpu != &pcpu_devices[0]) { pcpu->lowcore = (struct lowcore *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); @@ -197,20 +202,27 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) panic_stack = __get_free_page(GFP_KERNEL); if (!pcpu->lowcore || !panic_stack || !async_stack) goto out; + if (MACHINE_HAS_VX || MACHINE_HAS_GS) { + mcesa_origin = (unsigned long) + kmem_cache_alloc(pcpu_mcesa_cache, GFP_KERNEL); + if (!mcesa_origin) + goto out; + mcesa_bits = MACHINE_HAS_GS ? 11 : 0; + } } else { async_stack = pcpu->lowcore->async_stack - ASYNC_FRAME_OFFSET; panic_stack = pcpu->lowcore->panic_stack - PANIC_FRAME_OFFSET; + mcesa_origin = pcpu->lowcore->mcesad & MCESA_ORIGIN_MASK; + mcesa_bits = pcpu->lowcore->mcesad & MCESA_LC_MASK; } lc = pcpu->lowcore; memcpy(lc, &S390_lowcore, 512); memset((char *) lc + 512, 0, sizeof(*lc) - 512); lc->async_stack = async_stack + ASYNC_FRAME_OFFSET; lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET; + lc->mcesad = mcesa_origin | mcesa_bits; lc->cpu_nr = cpu; lc->spinlock_lockval = arch_spin_lockval(cpu); - if (MACHINE_HAS_VX) - lc->vector_save_area_addr = - (unsigned long) &lc->vector_save_area; if (vdso_alloc_per_cpu(lc)) goto out; lowcore_ptr[cpu] = lc; @@ -218,6 +230,9 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) return 0; out: if (pcpu != &pcpu_devices[0]) { + if (mcesa_origin) + kmem_cache_free(pcpu_mcesa_cache, + (void *) mcesa_origin); free_page(panic_stack); free_pages(async_stack, ASYNC_ORDER); free_pages((unsigned long) pcpu->lowcore, LC_ORDER); @@ -229,11 +244,17 @@ out: static void pcpu_free_lowcore(struct pcpu *pcpu) { + unsigned long mcesa_origin; + pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, 0); lowcore_ptr[pcpu - pcpu_devices] = NULL; vdso_free_per_cpu(pcpu->lowcore); if (pcpu == &pcpu_devices[0]) return; + if (MACHINE_HAS_VX || MACHINE_HAS_GS) { + mcesa_origin = pcpu->lowcore->mcesad & MCESA_ORIGIN_MASK; + kmem_cache_free(pcpu_mcesa_cache, (void *) mcesa_origin); + } free_page(pcpu->lowcore->panic_stack-PANIC_FRAME_OFFSET); free_pages(pcpu->lowcore->async_stack-ASYNC_FRAME_OFFSET, ASYNC_ORDER); free_pages((unsigned long) pcpu->lowcore, LC_ORDER); @@ -550,9 +571,11 @@ int smp_store_status(int cpu) if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_STATUS_AT_ADDRESS, pa) != SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; - if (!MACHINE_HAS_VX) + if (!MACHINE_HAS_VX && !MACHINE_HAS_GS) return 0; - pa = __pa(pcpu->lowcore->vector_save_area_addr); + pa = __pa(pcpu->lowcore->mcesad & MCESA_ORIGIN_MASK); + if (MACHINE_HAS_GS) + pa |= pcpu->lowcore->mcesad & MCESA_LC_MASK; if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS, pa) != SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; @@ -897,25 +920,33 @@ void __init smp_fill_possible_mask(void) void __init smp_prepare_cpus(unsigned int max_cpus) { + unsigned long size; + /* request the 0x1201 emergency signal external interrupt */ if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt)) panic("Couldn't request external interrupt 0x1201"); /* request the 0x1202 external call external interrupt */ if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt)) panic("Couldn't request external interrupt 0x1202"); + /* create slab cache for the machine-check-extended-save-areas */ + if (MACHINE_HAS_VX || MACHINE_HAS_GS) { + size = 1UL << (MACHINE_HAS_GS ? 11 : 10); + pcpu_mcesa_cache = kmem_cache_create("nmi_save_areas", + size, size, 0, NULL); + if (!pcpu_mcesa_cache) + panic("Couldn't create nmi save area cache"); + } } void __init smp_prepare_boot_cpu(void) { struct pcpu *pcpu = pcpu_devices; + WARN_ON(!cpu_present(0) || !cpu_online(0)); pcpu->state = CPU_STATE_CONFIGURED; - pcpu->address = stap(); pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix(); S390_lowcore.percpu_offset = __per_cpu_offset[0]; smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); - set_cpu_present(0, true); - set_cpu_online(0, true); } void __init smp_cpus_done(unsigned int max_cpus) @@ -924,6 +955,7 @@ void __init smp_cpus_done(unsigned int max_cpus) void __init smp_setup_processor_id(void) { + pcpu_devices[0].address = stap(); S390_lowcore.cpu_nr = 0; S390_lowcore.spinlock_lockval = arch_spin_lockval(0); } diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 9b59e6212d8f..54fce7b065de 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -386,3 +386,5 @@ SYSCALL(sys_mlock2,compat_sys_mlock2) SYSCALL(sys_copy_file_range,compat_sys_copy_file_range) /* 375 */ SYSCALL(sys_preadv2,compat_sys_preadv2) SYSCALL(sys_pwritev2,compat_sys_pwritev2) +SYSCALL(sys_s390_guarded_storage,compat_sys_s390_guarded_storage) /* 378 */ +SYSCALL(sys_statx,compat_sys_statx) diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 12b6b138e354..eefcb54872a5 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -4,6 +4,7 @@ * Martin Schwidefsky <schwidefsky@de.ibm.com>, */ +#include <linux/debugfs.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/proc_fs.h> @@ -13,6 +14,7 @@ #include <linux/export.h> #include <linux/slab.h> #include <asm/ebcdic.h> +#include <asm/debug.h> #include <asm/sysinfo.h> #include <asm/cpcmd.h> #include <asm/topology.h> @@ -485,3 +487,99 @@ void calibrate_delay(void) "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100); } + +#ifdef CONFIG_DEBUG_FS + +#define STSI_FILE(fc, s1, s2) \ +static int stsi_open_##fc##_##s1##_##s2(struct inode *inode, struct file *file)\ +{ \ + file->private_data = (void *) get_zeroed_page(GFP_KERNEL); \ + if (!file->private_data) \ + return -ENOMEM; \ + if (stsi(file->private_data, fc, s1, s2)) { \ + free_page((unsigned long)file->private_data); \ + file->private_data = NULL; \ + return -EACCES; \ + } \ + return nonseekable_open(inode, file); \ +} \ + \ +static const struct file_operations stsi_##fc##_##s1##_##s2##_fs_ops = { \ + .open = stsi_open_##fc##_##s1##_##s2, \ + .release = stsi_release, \ + .read = stsi_read, \ + .llseek = no_llseek, \ +}; + +static int stsi_release(struct inode *inode, struct file *file) +{ + free_page((unsigned long)file->private_data); + return 0; +} + +static ssize_t stsi_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) +{ + return simple_read_from_buffer(buf, size, ppos, file->private_data, PAGE_SIZE); +} + +STSI_FILE( 1, 1, 1); +STSI_FILE( 1, 2, 1); +STSI_FILE( 1, 2, 2); +STSI_FILE( 2, 2, 1); +STSI_FILE( 2, 2, 2); +STSI_FILE( 3, 2, 2); +STSI_FILE(15, 1, 2); +STSI_FILE(15, 1, 3); +STSI_FILE(15, 1, 4); +STSI_FILE(15, 1, 5); +STSI_FILE(15, 1, 6); + +struct stsi_file { + const struct file_operations *fops; + char *name; +}; + +static struct stsi_file stsi_file[] __initdata = { + {.fops = &stsi_1_1_1_fs_ops, .name = "1_1_1"}, + {.fops = &stsi_1_2_1_fs_ops, .name = "1_2_1"}, + {.fops = &stsi_1_2_2_fs_ops, .name = "1_2_2"}, + {.fops = &stsi_2_2_1_fs_ops, .name = "2_2_1"}, + {.fops = &stsi_2_2_2_fs_ops, .name = "2_2_2"}, + {.fops = &stsi_3_2_2_fs_ops, .name = "3_2_2"}, + {.fops = &stsi_15_1_2_fs_ops, .name = "15_1_2"}, + {.fops = &stsi_15_1_3_fs_ops, .name = "15_1_3"}, + {.fops = &stsi_15_1_4_fs_ops, .name = "15_1_4"}, + {.fops = &stsi_15_1_5_fs_ops, .name = "15_1_5"}, + {.fops = &stsi_15_1_6_fs_ops, .name = "15_1_6"}, +}; + +static u8 stsi_0_0_0; + +static __init int stsi_init_debugfs(void) +{ + struct dentry *stsi_root; + struct stsi_file *sf; + int lvl, i; + + stsi_root = debugfs_create_dir("stsi", arch_debugfs_dir); + if (IS_ERR_OR_NULL(stsi_root)) + return 0; + lvl = stsi(NULL, 0, 0, 0); + if (lvl > 0) + stsi_0_0_0 = lvl; + debugfs_create_u8("0_0_0", 0400, stsi_root, &stsi_0_0_0); + for (i = 0; i < ARRAY_SIZE(stsi_file); i++) { + sf = &stsi_file[i]; + debugfs_create_file(sf->name, 0400, stsi_root, NULL, sf->fops); + } + if (IS_ENABLED(CONFIG_SCHED_TOPOLOGY) && MACHINE_HAS_TOPOLOGY) { + char link_to[10]; + + sprintf(link_to, "15_1_%d", topology_mnest_limit()); + debugfs_create_symlink("topology", stsi_root, link_to); + } + return 0; +} +device_initcall(stsi_init_debugfs); + +#endif /* CONFIG_DEBUG_FS */ diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c31da46bc037..c3a52f9a69a0 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -158,7 +158,9 @@ void init_cpu_timer(void) cd->mult = 16777; cd->shift = 12; cd->min_delta_ns = 1; + cd->min_delta_ticks = 1; cd->max_delta_ns = LONG_MAX; + cd->max_delta_ticks = ULONG_MAX; cd->rating = 400; cd->cpumask = cpumask_of(cpu); cd->set_next_event = s390_next_event; diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 17660e800e74..bb47c92476f0 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -83,6 +83,8 @@ static cpumask_t cpu_thread_map(unsigned int cpu) return mask; } +#define TOPOLOGY_CORE_BITS 64 + static void add_cpus_to_mask(struct topology_core *tl_core, struct mask_info *drawer, struct mask_info *book, @@ -91,7 +93,7 @@ static void add_cpus_to_mask(struct topology_core *tl_core, struct cpu_topology_s390 *topo; unsigned int core; - for_each_set_bit(core, &tl_core->mask[0], TOPOLOGY_CORE_BITS) { + for_each_set_bit(core, &tl_core->mask, TOPOLOGY_CORE_BITS) { unsigned int rcore; int lcpu, i; @@ -244,7 +246,7 @@ static void update_cpu_masks(void) void store_topology(struct sysinfo_15_1_x *info) { - stsi(info, 15, 1, min(topology_max_mnest, 4)); + stsi(info, 15, 1, topology_mnest_limit()); } static int __arch_update_cpu_topology(void) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 5ccf95396251..72307f108c40 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -63,11 +63,9 @@ SECTIONS . = ALIGN(PAGE_SIZE); __start_ro_after_init = .; - __start_data_ro_after_init = .; .data..ro_after_init : { *(.data..ro_after_init) } - __end_data_ro_after_init = .; EXCEPTION_TABLE(16) . = ALIGN(PAGE_SIZE); __end_ro_after_init = .; diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index c14fc9029912..072d84ba42a3 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -111,7 +111,7 @@ static inline u64 scale_vtime(u64 vtime) } static void account_system_index_scaled(struct task_struct *p, - cputime_t cputime, cputime_t scaled, + u64 cputime, u64 scaled, enum cpu_usage_stat index) { p->stimescaled += cputime_to_nsecs(scaled); diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index d55c829a5944..ddbffb715b40 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -168,8 +168,7 @@ union page_table_entry { unsigned long z : 1; /* Zero Bit */ unsigned long i : 1; /* Page-Invalid Bit */ unsigned long p : 1; /* DAT-Protection Bit */ - unsigned long co : 1; /* Change-Recording Override */ - unsigned long : 8; + unsigned long : 9; }; }; @@ -745,8 +744,6 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva, return PGM_PAGE_TRANSLATION; if (pte.z) return PGM_TRANSLATION_SPEC; - if (pte.co && !edat1) - return PGM_TRANSLATION_SPEC; dat_protection |= pte.p; raddr.pfra = pte.pfra; real_address: @@ -1182,7 +1179,7 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, rc = gmap_read_table(sg->parent, pgt + vaddr.px * 8, &pte.val); if (!rc && pte.i) rc = PGM_PAGE_TRANSLATION; - if (!rc && (pte.z || (pte.co && sg->edat_level < 1))) + if (!rc && pte.z) rc = PGM_TRANSLATION_SPEC; shadow_page: pte.p |= dat_protection; diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 0f8f14199734..169558dc7daf 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -420,8 +420,8 @@ static int __write_machine_check(struct kvm_vcpu *vcpu, save_access_regs(vcpu->run->s.regs.acrs); /* Extended save area */ - rc = read_guest_lc(vcpu, __LC_VX_SAVE_AREA_ADDR, &ext_sa_addr, - sizeof(unsigned long)); + rc = read_guest_lc(vcpu, __LC_MCESAD, &ext_sa_addr, + sizeof(unsigned long)); /* Only bits 0-53 are used for address formation */ ext_sa_addr &= ~0x3ffUL; if (!rc && mci.vr && ext_sa_addr && test_kvm_facility(vcpu->kvm, 129)) { diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index fd6cd05bb6a7..d5c5c911821a 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -273,7 +273,7 @@ static void kvm_s390_cpu_feat_init(void) kvm_s390_available_subfunc.pcc); } if (test_facility(57)) /* MSA5 */ - __cpacf_query(CPACF_PPNO, (cpacf_mask_t *) + __cpacf_query(CPACF_PRNO, (cpacf_mask_t *) kvm_s390_available_subfunc.ppno); if (MACHINE_HAS_ESOP) @@ -1512,9 +1512,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT; } else { if (sclp.hamax == U64_MAX) - kvm->arch.mem_limit = TASK_MAX_SIZE; + kvm->arch.mem_limit = TASK_SIZE_MAX; else - kvm->arch.mem_limit = min_t(unsigned long, TASK_MAX_SIZE, + kvm->arch.mem_limit = min_t(unsigned long, TASK_SIZE_MAX, sclp.hamax + 1); kvm->arch.gmap = gmap_create(current->mm, kvm->arch.mem_limit - 1); if (!kvm->arch.gmap) diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index ba427eb6f14c..ffb15bd4c593 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -17,7 +17,7 @@ int spin_retry = -1; static int __init spin_retry_init(void) { if (spin_retry < 0) - spin_retry = MACHINE_HAS_CAD ? 10 : 1000; + spin_retry = 1000; return 0; } early_initcall(spin_retry_init); @@ -32,23 +32,17 @@ static int __init spin_retry_setup(char *str) } __setup("spin_retry=", spin_retry_setup); -static inline void _raw_compare_and_delay(unsigned int *lock, unsigned int old) -{ - asm(".insn rsy,0xeb0000000022,%0,0,%1" : : "d" (old), "Q" (*lock)); -} - void arch_spin_lock_wait(arch_spinlock_t *lp) { - unsigned int cpu = SPINLOCK_LOCKVAL; - unsigned int owner; - int count, first_diag; + int cpu = SPINLOCK_LOCKVAL; + int owner, count, first_diag; first_diag = 1; while (1) { owner = ACCESS_ONCE(lp->lock); /* Try to get the lock if it is free. */ if (!owner) { - if (_raw_compare_and_swap(&lp->lock, 0, cpu)) + if (__atomic_cmpxchg_bool(&lp->lock, 0, cpu)) return; continue; } @@ -61,8 +55,6 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) /* Loop for a while on the lock value. */ count = spin_retry; do { - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&lp->lock, owner); owner = ACCESS_ONCE(lp->lock); } while (owner && count-- > 0); if (!owner) @@ -82,9 +74,8 @@ EXPORT_SYMBOL(arch_spin_lock_wait); void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) { - unsigned int cpu = SPINLOCK_LOCKVAL; - unsigned int owner; - int count, first_diag; + int cpu = SPINLOCK_LOCKVAL; + int owner, count, first_diag; local_irq_restore(flags); first_diag = 1; @@ -93,7 +84,7 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) /* Try to get the lock if it is free. */ if (!owner) { local_irq_disable(); - if (_raw_compare_and_swap(&lp->lock, 0, cpu)) + if (__atomic_cmpxchg_bool(&lp->lock, 0, cpu)) return; local_irq_restore(flags); continue; @@ -107,8 +98,6 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) /* Loop for a while on the lock value. */ count = spin_retry; do { - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&lp->lock, owner); owner = ACCESS_ONCE(lp->lock); } while (owner && count-- > 0); if (!owner) @@ -128,18 +117,16 @@ EXPORT_SYMBOL(arch_spin_lock_wait_flags); int arch_spin_trylock_retry(arch_spinlock_t *lp) { - unsigned int cpu = SPINLOCK_LOCKVAL; - unsigned int owner; - int count; + int cpu = SPINLOCK_LOCKVAL; + int owner, count; for (count = spin_retry; count > 0; count--) { owner = READ_ONCE(lp->lock); /* Try to get the lock if it is free. */ if (!owner) { - if (_raw_compare_and_swap(&lp->lock, 0, cpu)) + if (__atomic_cmpxchg_bool(&lp->lock, 0, cpu)) return 1; - } else if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&lp->lock, owner); + } } return 0; } @@ -147,8 +134,8 @@ EXPORT_SYMBOL(arch_spin_trylock_retry); void _raw_read_lock_wait(arch_rwlock_t *rw) { - unsigned int owner, old; int count = spin_retry; + int owner, old; #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES __RAW_LOCK(&rw->lock, -1, __RAW_OP_ADD); @@ -162,12 +149,9 @@ void _raw_read_lock_wait(arch_rwlock_t *rw) } old = ACCESS_ONCE(rw->lock); owner = ACCESS_ONCE(rw->owner); - if ((int) old < 0) { - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&rw->lock, old); + if (old < 0) continue; - } - if (_raw_compare_and_swap(&rw->lock, old, old + 1)) + if (__atomic_cmpxchg_bool(&rw->lock, old, old + 1)) return; } } @@ -175,17 +159,14 @@ EXPORT_SYMBOL(_raw_read_lock_wait); int _raw_read_trylock_retry(arch_rwlock_t *rw) { - unsigned int old; int count = spin_retry; + int old; while (count-- > 0) { old = ACCESS_ONCE(rw->lock); - if ((int) old < 0) { - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&rw->lock, old); + if (old < 0) continue; - } - if (_raw_compare_and_swap(&rw->lock, old, old + 1)) + if (__atomic_cmpxchg_bool(&rw->lock, old, old + 1)) return 1; } return 0; @@ -194,10 +175,10 @@ EXPORT_SYMBOL(_raw_read_trylock_retry); #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES -void _raw_write_lock_wait(arch_rwlock_t *rw, unsigned int prev) +void _raw_write_lock_wait(arch_rwlock_t *rw, int prev) { - unsigned int owner, old; int count = spin_retry; + int owner, old; owner = 0; while (1) { @@ -209,14 +190,12 @@ void _raw_write_lock_wait(arch_rwlock_t *rw, unsigned int prev) old = ACCESS_ONCE(rw->lock); owner = ACCESS_ONCE(rw->owner); smp_mb(); - if ((int) old >= 0) { + if (old >= 0) { prev = __RAW_LOCK(&rw->lock, 0x80000000, __RAW_OP_OR); old = prev; } - if ((old & 0x7fffffff) == 0 && (int) prev >= 0) + if ((old & 0x7fffffff) == 0 && prev >= 0) break; - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&rw->lock, old); } } EXPORT_SYMBOL(_raw_write_lock_wait); @@ -225,8 +204,8 @@ EXPORT_SYMBOL(_raw_write_lock_wait); void _raw_write_lock_wait(arch_rwlock_t *rw) { - unsigned int owner, old, prev; int count = spin_retry; + int owner, old, prev; prev = 0x80000000; owner = 0; @@ -238,15 +217,13 @@ void _raw_write_lock_wait(arch_rwlock_t *rw) } old = ACCESS_ONCE(rw->lock); owner = ACCESS_ONCE(rw->owner); - if ((int) old >= 0 && - _raw_compare_and_swap(&rw->lock, old, old | 0x80000000)) + if (old >= 0 && + __atomic_cmpxchg_bool(&rw->lock, old, old | 0x80000000)) prev = old; else smp_mb(); - if ((old & 0x7fffffff) == 0 && (int) prev >= 0) + if ((old & 0x7fffffff) == 0 && prev >= 0) break; - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&rw->lock, old); } } EXPORT_SYMBOL(_raw_write_lock_wait); @@ -255,24 +232,21 @@ EXPORT_SYMBOL(_raw_write_lock_wait); int _raw_write_trylock_retry(arch_rwlock_t *rw) { - unsigned int old; int count = spin_retry; + int old; while (count-- > 0) { old = ACCESS_ONCE(rw->lock); - if (old) { - if (MACHINE_HAS_CAD) - _raw_compare_and_delay(&rw->lock, old); + if (old) continue; - } - if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) + if (__atomic_cmpxchg_bool(&rw->lock, 0, 0x80000000)) return 1; } return 0; } EXPORT_SYMBOL(_raw_write_trylock_retry); -void arch_lock_relax(unsigned int cpu) +void arch_lock_relax(int cpu) { if (!cpu) return; diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c index f481fcde067b..1e5bb2b86c42 100644 --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -26,7 +26,7 @@ static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr tmp1 = -4096UL; asm volatile( "0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n" - "9: jz 7f\n" + "6: jz 4f\n" "1: algr %0,%3\n" " slgr %1,%3\n" " slgr %2,%3\n" @@ -35,23 +35,13 @@ static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr " nr %4,%3\n" /* %4 = (ptr + 4095) & -4096 */ " slgr %4,%1\n" " clgr %0,%4\n" /* copy crosses next page boundary? */ - " jnh 4f\n" + " jnh 5f\n" "3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n" - "10:slgr %0,%4\n" - " algr %2,%4\n" - "4: lghi %4,-1\n" - " algr %4,%0\n" /* copy remaining size, subtract 1 */ - " bras %3,6f\n" /* memset loop */ - " xc 0(1,%2),0(%2)\n" - "5: xc 0(256,%2),0(%2)\n" - " la %2,256(%2)\n" - "6: aghi %4,-256\n" - " jnm 5b\n" - " ex %4,0(%3)\n" - " j 8f\n" - "7: slgr %0,%0\n" - "8:\n" - EX_TABLE(0b,2b) EX_TABLE(3b,4b) EX_TABLE(9b,2b) EX_TABLE(10b,4b) + "7: slgr %0,%4\n" + " j 5f\n" + "4: slgr %0,%0\n" + "5:\n" + EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b) : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) : "d" (reg0) : "cc", "memory"); return size; @@ -67,49 +57,38 @@ static inline unsigned long copy_from_user_mvcp(void *x, const void __user *ptr, asm volatile( " sacf 0\n" "0: mvcp 0(%0,%2),0(%1),%3\n" - "10:jz 8f\n" + "7: jz 5f\n" "1: algr %0,%3\n" " la %1,256(%1)\n" " la %2,256(%2)\n" "2: mvcp 0(%0,%2),0(%1),%3\n" - "11:jnz 1b\n" - " j 8f\n" + "8: jnz 1b\n" + " j 5f\n" "3: la %4,255(%1)\n" /* %4 = ptr + 255 */ " lghi %3,-4096\n" " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */ " slgr %4,%1\n" " clgr %0,%4\n" /* copy crosses next page boundary? */ - " jnh 5f\n" + " jnh 6f\n" "4: mvcp 0(%4,%2),0(%1),%3\n" - "12:slgr %0,%4\n" - " algr %2,%4\n" - "5: lghi %4,-1\n" - " algr %4,%0\n" /* copy remaining size, subtract 1 */ - " bras %3,7f\n" /* memset loop */ - " xc 0(1,%2),0(%2)\n" - "6: xc 0(256,%2),0(%2)\n" - " la %2,256(%2)\n" - "7: aghi %4,-256\n" - " jnm 6b\n" - " ex %4,0(%3)\n" - " j 9f\n" - "8: slgr %0,%0\n" - "9: sacf 768\n" - EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b) - EX_TABLE(10b,3b) EX_TABLE(11b,3b) EX_TABLE(12b,5b) + "9: slgr %0,%4\n" + " j 6f\n" + "5: slgr %0,%0\n" + "6: sacf 768\n" + EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b) + EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b) : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) : : "cc", "memory"); return size; } -unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) +unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - check_object_size(to, n, false); if (static_branch_likely(&have_mvcos)) return copy_from_user_mvcos(to, from, n); return copy_from_user_mvcp(to, from, n); } -EXPORT_SYMBOL(__copy_from_user); +EXPORT_SYMBOL(raw_copy_from_user); static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x, unsigned long size) @@ -176,14 +155,13 @@ static inline unsigned long copy_to_user_mvcs(void __user *ptr, const void *x, return size; } -unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) +unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - check_object_size(from, n, true); if (static_branch_likely(&have_mvcos)) return copy_to_user_mvcos(to, from, n); return copy_to_user_mvcs(to, from, n); } -EXPORT_SYMBOL(__copy_to_user); +EXPORT_SYMBOL(raw_copy_to_user); static inline unsigned long copy_in_user_mvcos(void __user *to, const void __user *from, unsigned long size) @@ -240,13 +218,13 @@ static inline unsigned long copy_in_user_mvc(void __user *to, const void __user return size; } -unsigned long __copy_in_user(void __user *to, const void __user *from, unsigned long n) +unsigned long raw_copy_in_user(void __user *to, const void __user *from, unsigned long n) { if (static_branch_likely(&have_mvcos)) return copy_in_user_mvcos(to, from, n); return copy_in_user_mvc(to, from, n); } -EXPORT_SYMBOL(__copy_in_user); +EXPORT_SYMBOL(raw_copy_in_user); static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size) { diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index a07b1ec1391d..7f6db1e6c048 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -431,7 +431,7 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from, if ((from | to | len) & (PMD_SIZE - 1)) return -EINVAL; if (len == 0 || from + len < from || to + len < to || - from + len - 1 > TASK_MAX_SIZE || to + len - 1 > gmap->asce_end) + from + len - 1 > TASK_SIZE_MAX || to + len - 1 > gmap->asce_end) return -EINVAL; flush = 0; @@ -2004,20 +2004,12 @@ EXPORT_SYMBOL_GPL(gmap_shadow_page); * Called with sg->parent->shadow_lock. */ static void gmap_shadow_notify(struct gmap *sg, unsigned long vmaddr, - unsigned long offset, pte_t *pte) + unsigned long gaddr, pte_t *pte) { struct gmap_rmap *rmap, *rnext, *head; - unsigned long gaddr, start, end, bits, raddr; - unsigned long *table; + unsigned long start, end, bits, raddr; BUG_ON(!gmap_is_shadow(sg)); - spin_lock(&sg->parent->guest_table_lock); - table = radix_tree_lookup(&sg->parent->host_to_guest, - vmaddr >> PMD_SHIFT); - gaddr = table ? __gmap_segment_gaddr(table) + offset : 0; - spin_unlock(&sg->parent->guest_table_lock); - if (!table) - return; spin_lock(&sg->guest_table_lock); if (sg->removed) { @@ -2076,7 +2068,7 @@ static void gmap_shadow_notify(struct gmap *sg, unsigned long vmaddr, void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, pte_t *pte, unsigned long bits) { - unsigned long offset, gaddr; + unsigned long offset, gaddr = 0; unsigned long *table; struct gmap *gmap, *sg, *next; @@ -2084,22 +2076,23 @@ void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, offset = offset * (4096 / sizeof(pte_t)); rcu_read_lock(); list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { - if (!list_empty(&gmap->children) && (bits & PGSTE_VSIE_BIT)) { - spin_lock(&gmap->shadow_lock); - list_for_each_entry_safe(sg, next, - &gmap->children, list) - gmap_shadow_notify(sg, vmaddr, offset, pte); - spin_unlock(&gmap->shadow_lock); - } - if (!(bits & PGSTE_IN_BIT)) - continue; spin_lock(&gmap->guest_table_lock); table = radix_tree_lookup(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); if (table) gaddr = __gmap_segment_gaddr(table) + offset; spin_unlock(&gmap->guest_table_lock); - if (table) + if (!table) + continue; + + if (!list_empty(&gmap->children) && (bits & PGSTE_VSIE_BIT)) { + spin_lock(&gmap->shadow_lock); + list_for_each_entry_safe(sg, next, + &gmap->children, list) + gmap_shadow_notify(sg, vmaddr, gaddr, pte); + spin_unlock(&gmap->shadow_lock); + } + if (bits & PGSTE_IN_BIT) gmap_call_notifier(gmap, gaddr, gaddr + PAGE_SIZE - 1); } rcu_read_unlock(); diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 18d4107e10ee..b7b779c40a5b 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -211,7 +211,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if ((end <= start) || (end > TASK_SIZE)) + if ((end <= start) || (end > mm->context.asce_limit)) return 0; /* * local_irq_save() doesn't prevent pagetable teardown, but does diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 50618614881f..b017daed6887 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -89,19 +89,20 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct vm_unmapped_area_info info; + int rc; if (len > TASK_SIZE - mmap_min_addr) return -ENOMEM; if (flags & MAP_FIXED) - return addr; + goto check_asce_limit; if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <= vma->vm_start)) - return addr; + goto check_asce_limit; } info.flags = 0; @@ -113,7 +114,18 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, else info.align_mask = 0; info.align_offset = pgoff << PAGE_SHIFT; - return vm_unmapped_area(&info); + addr = vm_unmapped_area(&info); + if (addr & ~PAGE_MASK) + return addr; + +check_asce_limit: + if (addr + len > current->mm->context.asce_limit) { + rc = crst_table_upgrade(mm); + if (rc) + return (unsigned long) rc; + } + + return addr; } unsigned long @@ -125,13 +137,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, struct mm_struct *mm = current->mm; unsigned long addr = addr0; struct vm_unmapped_area_info info; + int rc; /* requested length too big for entire address space */ if (len > TASK_SIZE - mmap_min_addr) return -ENOMEM; if (flags & MAP_FIXED) - return addr; + goto check_asce_limit; /* requesting a specific address */ if (addr) { @@ -139,7 +152,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr); if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <= vma->vm_start)) - return addr; + goto check_asce_limit; } info.flags = VM_UNMAPPED_AREA_TOPDOWN; @@ -165,65 +178,20 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.low_limit = TASK_UNMAPPED_BASE; info.high_limit = TASK_SIZE; addr = vm_unmapped_area(&info); + if (addr & ~PAGE_MASK) + return addr; } - return addr; -} - -int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) -{ - if (is_compat_task() || TASK_SIZE >= TASK_MAX_SIZE) - return 0; - if (!(flags & MAP_FIXED)) - addr = 0; - if ((addr + len) >= TASK_SIZE) - return crst_table_upgrade(current->mm); - return 0; -} - -static unsigned long -s390_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct mm_struct *mm = current->mm; - unsigned long area; - int rc; - - area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); - if (!(area & ~PAGE_MASK)) - return area; - if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < TASK_MAX_SIZE) { - /* Upgrade the page table to 4 levels and retry. */ +check_asce_limit: + if (addr + len > current->mm->context.asce_limit) { rc = crst_table_upgrade(mm); if (rc) return (unsigned long) rc; - area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); } - return area; -} - -static unsigned long -s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, - const unsigned long len, const unsigned long pgoff, - const unsigned long flags) -{ - struct mm_struct *mm = current->mm; - unsigned long area; - int rc; - area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); - if (!(area & ~PAGE_MASK)) - return area; - if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < TASK_MAX_SIZE) { - /* Upgrade the page table to 4 levels and retry. */ - rc = crst_table_upgrade(mm); - if (rc) - return (unsigned long) rc; - area = arch_get_unmapped_area_topdown(filp, addr, len, - pgoff, flags); - } - return area; + return addr; } + /* * This function, called very early during the creation of a new * process VM image, sets up which VM layout function to use: @@ -241,9 +209,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm) */ if (mmap_is_legacy()) { mm->mmap_base = mmap_base_legacy(random_factor); - mm->get_unmapped_area = s390_get_unmapped_area; + mm->get_unmapped_area = arch_get_unmapped_area; } else { mm->mmap_base = mmap_base(random_factor); - mm->get_unmapped_area = s390_get_unmapped_area_topdown; + mm->get_unmapped_area = arch_get_unmapped_area_topdown; } } diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c index 3330ea124eec..69a7b01ae746 100644 --- a/arch/s390/mm/page-states.c +++ b/arch/s390/mm/page-states.c @@ -13,8 +13,7 @@ #include <linux/gfp.h> #include <linux/init.h> -#define ESSA_SET_STABLE 1 -#define ESSA_SET_UNUSED 2 +#include <asm/page-states.h> static int cmma_flag = 1; diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index fc5dc33bb141..fc321c5ec30e 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -94,7 +94,7 @@ static int walk_pte_level(pmd_t *pmdp, unsigned long addr, unsigned long end, new = pte_wrprotect(new); else if (flags & SET_MEMORY_RW) new = pte_mkwrite(pte_mkdirty(new)); - if ((flags & SET_MEMORY_NX) && MACHINE_HAS_NX) + if (flags & SET_MEMORY_NX) pte_val(new) |= _PAGE_NOEXEC; else if (flags & SET_MEMORY_X) pte_val(new) &= ~_PAGE_NOEXEC; @@ -144,7 +144,7 @@ static void modify_pmd_page(pmd_t *pmdp, unsigned long addr, new = pmd_wrprotect(new); else if (flags & SET_MEMORY_RW) new = pmd_mkwrite(pmd_mkdirty(new)); - if ((flags & SET_MEMORY_NX) && MACHINE_HAS_NX) + if (flags & SET_MEMORY_NX) pmd_val(new) |= _SEGMENT_ENTRY_NOEXEC; else if (flags & SET_MEMORY_X) pmd_val(new) &= ~_SEGMENT_ENTRY_NOEXEC; @@ -221,7 +221,7 @@ static void modify_pud_page(pud_t *pudp, unsigned long addr, new = pud_wrprotect(new); else if (flags & SET_MEMORY_RW) new = pud_mkwrite(pud_mkdirty(new)); - if ((flags & SET_MEMORY_NX) && MACHINE_HAS_NX) + if (flags & SET_MEMORY_NX) pud_val(new) |= _REGION_ENTRY_NOEXEC; else if (flags & SET_MEMORY_X) pud_val(new) &= ~_REGION_ENTRY_NOEXEC; @@ -288,6 +288,10 @@ static int change_page_attr(unsigned long addr, unsigned long end, int __set_memory(unsigned long addr, int numpages, unsigned long flags) { + if (!MACHINE_HAS_NX) + flags &= ~(SET_MEMORY_NX | SET_MEMORY_X); + if (!flags) + return 0; addr &= PAGE_MASK; return change_page_attr(addr, addr + numpages * PAGE_SIZE, flags); } diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c index 995f78532cc2..f502cbe657af 100644 --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -95,7 +95,6 @@ int crst_table_upgrade(struct mm_struct *mm) mm->context.asce_limit = 1UL << 53; mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | _ASCE_USER_BITS | _ASCE_TYPE_REGION2; - mm->task_size = mm->context.asce_limit; spin_unlock_bh(&mm->page_table_lock); on_each_cpu(__crst_table_upgrade, mm, 0); @@ -119,7 +118,6 @@ void crst_table_downgrade(struct mm_struct *mm) mm->context.asce_limit = 1UL << 31; mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT; - mm->task_size = mm->context.asce_limit; crst_table_free(mm, (unsigned long *) pgd); if (current->active_mm == mm) @@ -144,7 +142,7 @@ struct page *page_table_alloc_pgste(struct mm_struct *mm) struct page *page; unsigned long *table; - page = alloc_page(GFP_KERNEL|__GFP_REPEAT); + page = alloc_page(GFP_KERNEL); if (page) { table = (unsigned long *) page_to_phys(page); clear_table(table, _PAGE_INVALID, PAGE_SIZE/2); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index b48dc5f1900b..947b66a5cdba 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -23,6 +23,7 @@ #include <asm/tlb.h> #include <asm/tlbflush.h> #include <asm/mmu_context.h> +#include <asm/page-states.h> static inline pte_t ptep_flush_direct(struct mm_struct *mm, unsigned long addr, pte_t *ptep) @@ -608,12 +609,29 @@ void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep) bool test_and_clear_guest_dirty(struct mm_struct *mm, unsigned long addr) { spinlock_t *ptl; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; pgste_t pgste; pte_t *ptep; pte_t pte; bool dirty; - ptep = get_locked_pte(mm, addr, &ptl); + pgd = pgd_offset(mm, addr); + pud = pud_alloc(mm, pgd, addr); + if (!pud) + return false; + pmd = pmd_alloc(mm, pud, addr); + if (!pmd) + return false; + /* We can't run guests backed by huge pages, but userspace can + * still set them up and then try to migrate them without any + * migration support. + */ + if (pmd_large(*pmd)) + return true; + + ptep = pte_alloc_map_lock(mm, pmd, addr, &ptl); if (unlikely(!ptep)) return false; @@ -770,4 +788,156 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, return 0; } EXPORT_SYMBOL(get_guest_storage_key); + +/** + * pgste_perform_essa - perform ESSA actions on the PGSTE. + * @mm: the memory context. It must have PGSTEs, no check is performed here! + * @hva: the host virtual address of the page whose PGSTE is to be processed + * @orc: the specific action to perform, see the ESSA_SET_* macros. + * @oldpte: the PTE will be saved there if the pointer is not NULL. + * @oldpgste: the old PGSTE will be saved there if the pointer is not NULL. + * + * Return: 1 if the page is to be added to the CBRL, otherwise 0, + * or < 0 in case of error. -EINVAL is returned for invalid values + * of orc, -EFAULT for invalid addresses. + */ +int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, + unsigned long *oldpte, unsigned long *oldpgste) +{ + unsigned long pgstev; + spinlock_t *ptl; + pgste_t pgste; + pte_t *ptep; + int res = 0; + + WARN_ON_ONCE(orc > ESSA_MAX); + if (unlikely(orc > ESSA_MAX)) + return -EINVAL; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; + pgste = pgste_get_lock(ptep); + pgstev = pgste_val(pgste); + if (oldpte) + *oldpte = pte_val(*ptep); + if (oldpgste) + *oldpgste = pgstev; + + switch (orc) { + case ESSA_GET_STATE: + break; + case ESSA_SET_STABLE: + pgstev &= ~_PGSTE_GPS_USAGE_MASK; + pgstev |= _PGSTE_GPS_USAGE_STABLE; + break; + case ESSA_SET_UNUSED: + pgstev &= ~_PGSTE_GPS_USAGE_MASK; + pgstev |= _PGSTE_GPS_USAGE_UNUSED; + if (pte_val(*ptep) & _PAGE_INVALID) + res = 1; + break; + case ESSA_SET_VOLATILE: + pgstev &= ~_PGSTE_GPS_USAGE_MASK; + pgstev |= _PGSTE_GPS_USAGE_VOLATILE; + if (pte_val(*ptep) & _PAGE_INVALID) + res = 1; + break; + case ESSA_SET_POT_VOLATILE: + pgstev &= ~_PGSTE_GPS_USAGE_MASK; + if (!(pte_val(*ptep) & _PAGE_INVALID)) { + pgstev |= _PGSTE_GPS_USAGE_POT_VOLATILE; + break; + } + if (pgstev & _PGSTE_GPS_ZERO) { + pgstev |= _PGSTE_GPS_USAGE_VOLATILE; + break; + } + if (!(pgstev & PGSTE_GC_BIT)) { + pgstev |= _PGSTE_GPS_USAGE_VOLATILE; + res = 1; + break; + } + break; + case ESSA_SET_STABLE_RESIDENT: + pgstev &= ~_PGSTE_GPS_USAGE_MASK; + pgstev |= _PGSTE_GPS_USAGE_STABLE; + /* + * Since the resident state can go away any time after this + * call, we will not make this page resident. We can revisit + * this decision if a guest will ever start using this. + */ + break; + case ESSA_SET_STABLE_IF_RESIDENT: + if (!(pte_val(*ptep) & _PAGE_INVALID)) { + pgstev &= ~_PGSTE_GPS_USAGE_MASK; + pgstev |= _PGSTE_GPS_USAGE_STABLE; + } + break; + default: + /* we should never get here! */ + break; + } + /* If we are discarding a page, set it to logical zero */ + if (res) + pgstev |= _PGSTE_GPS_ZERO; + + pgste_val(pgste) = pgstev; + pgste_set_unlock(ptep, pgste); + pte_unmap_unlock(ptep, ptl); + return res; +} +EXPORT_SYMBOL(pgste_perform_essa); + +/** + * set_pgste_bits - set specific PGSTE bits. + * @mm: the memory context. It must have PGSTEs, no check is performed here! + * @hva: the host virtual address of the page whose PGSTE is to be processed + * @bits: a bitmask representing the bits that will be touched + * @value: the values of the bits to be written. Only the bits in the mask + * will be written. + * + * Return: 0 on success, < 0 in case of error. + */ +int set_pgste_bits(struct mm_struct *mm, unsigned long hva, + unsigned long bits, unsigned long value) +{ + spinlock_t *ptl; + pgste_t new; + pte_t *ptep; + + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; + new = pgste_get_lock(ptep); + + pgste_val(new) &= ~bits; + pgste_val(new) |= value & bits; + + pgste_set_unlock(ptep, new); + pte_unmap_unlock(ptep, ptl); + return 0; +} +EXPORT_SYMBOL(set_pgste_bits); + +/** + * get_pgste - get the current PGSTE for the given address. + * @mm: the memory context. It must have PGSTEs, no check is performed here! + * @hva: the host virtual address of the page whose PGSTE is to be processed + * @pgstep: will be written with the current PGSTE for the given address. + * + * Return: 0 on success, < 0 in case of error. + */ +int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep) +{ + spinlock_t *ptl; + pte_t *ptep; + + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; + *pgstep = pgste_val(pgste_get(ptep)); + pte_unmap_unlock(ptep, ptl); + return 0; +} +EXPORT_SYMBOL(get_pgste); #endif diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 364b9d824be3..8051df109db3 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -60,16 +60,8 @@ static DEFINE_SPINLOCK(zpci_domain_lock); static struct airq_iv *zpci_aisb_iv; static struct airq_iv *zpci_aibv[ZPCI_NR_DEVICES]; -/* Adapter interrupt definitions */ -static void zpci_irq_handler(struct airq_struct *airq); - -static struct airq_struct zpci_airq = { - .handler = zpci_irq_handler, - .isc = PCI_ISC, -}; - #define ZPCI_IOMAP_ENTRIES \ - min(((unsigned long) CONFIG_PCI_NR_FUNCTIONS * PCI_BAR_COUNT), \ + min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2), \ ZPCI_IOMAP_MAX_ENTRIES) static DEFINE_SPINLOCK(zpci_iomap_lock); @@ -214,8 +206,6 @@ int zpci_fmb_disable_device(struct zpci_dev *zdev) return rc; } -#define ZPCI_PCIAS_CFGSPC 15 - static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) { u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); @@ -507,6 +497,11 @@ static void zpci_unmap_resources(struct pci_dev *pdev) } } +static struct airq_struct zpci_airq = { + .handler = zpci_irq_handler, + .isc = PCI_ISC, +}; + static int __init zpci_irq_init(void) { int rc; @@ -871,11 +866,6 @@ int zpci_report_error(struct pci_dev *pdev, } EXPORT_SYMBOL(zpci_report_error); -static inline int barsize(u8 size) -{ - return (size) ? (1 << size) >> 10 : 0; -} - static int zpci_mem_init(void) { BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) || diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index 926943a49ea5..e3a8d0f96652 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -4,6 +4,7 @@ header-y += generic-y += barrier.h generic-y += clkdev.h generic-y += current.h +generic-y += extable.h generic-y += irq_work.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h diff --git a/arch/score/include/asm/extable.h b/arch/score/include/asm/extable.h deleted file mode 100644 index c4423ccf830d..000000000000 --- a/arch/score/include/asm/extable.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _ASM_SCORE_EXTABLE_H -#define _ASM_SCORE_EXTABLE_H - -struct exception_table_entry { - unsigned long insn; - unsigned long fixup; -}; - -struct pt_regs; -extern int fixup_exception(struct pt_regs *regs); -#endif diff --git a/arch/score/include/asm/pgtable.h b/arch/score/include/asm/pgtable.h index 0553e5cd5985..46ff8fd678a7 100644 --- a/arch/score/include/asm/pgtable.h +++ b/arch/score/include/asm/pgtable.h @@ -2,6 +2,7 @@ #define _ASM_SCORE_PGTABLE_H #include <linux/const.h> +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #include <asm/fixmap.h> diff --git a/arch/score/include/asm/uaccess.h b/arch/score/include/asm/uaccess.h index db58ab98ec4b..916e5dbf0bfd 100644 --- a/arch/score/include/asm/uaccess.h +++ b/arch/score/include/asm/uaccess.h @@ -2,13 +2,8 @@ #define __SCORE_UACCESS_H #include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/thread_info.h> #include <asm/extable.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) #define segment_eq(a, b) ((a).seg == (b).seg) @@ -300,61 +295,19 @@ extern void __put_user_unknown(void); extern int __copy_tofrom_user(void *to, const void *from, unsigned long len); static inline unsigned long -copy_from_user(void *to, const void *from, unsigned long len) -{ - unsigned long res = len; - - if (likely(access_ok(VERIFY_READ, from, len))) - res = __copy_tofrom_user(to, from, len); - - if (unlikely(res)) - memset(to + (len - res), 0, res); - - return res; -} - -static inline unsigned long -copy_to_user(void *to, const void *from, unsigned long len) -{ - if (likely(access_ok(VERIFY_WRITE, to, len))) - len = __copy_tofrom_user(to, from, len); - - return len; -} - -static inline unsigned long -__copy_from_user(void *to, const void *from, unsigned long len) +raw_copy_from_user(void *to, const void __user *from, unsigned long len) { - unsigned long left = __copy_tofrom_user(to, from, len); - if (unlikely(left)) - memset(to + (len - left), 0, left); - return left; + return __copy_tofrom_user(to, (__force const void *)from, len); } -#define __copy_to_user(to, from, len) \ - __copy_tofrom_user((to), (from), (len)) - static inline unsigned long -__copy_to_user_inatomic(void *to, const void *from, unsigned long len) +raw_copy_to_user(void __user *to, const void *from, unsigned long len) { - return __copy_to_user(to, from, len); + return __copy_tofrom_user((__force void *)to, from, len); } -static inline unsigned long -__copy_from_user_inatomic(void *to, const void *from, unsigned long len) -{ - return __copy_tofrom_user(to, from, len); -} - -#define __copy_in_user(to, from, len) __copy_tofrom_user(to, from, len) - -static inline unsigned long -copy_in_user(void *to, const void *from, unsigned long len) -{ - if (access_ok(VERIFY_READ, from, len) && - access_ok(VERFITY_WRITE, to, len)) - return __copy_tofrom_user(to, from, len); -} +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * __clear_user: - Zero a block of memory in user space, with less checking. diff --git a/arch/score/kernel/time.c b/arch/score/kernel/time.c index 679b8d7b0350..29aafc741f69 100644 --- a/arch/score/kernel/time.c +++ b/arch/score/kernel/time.c @@ -81,8 +81,10 @@ void __init time_init(void) score_clockevent.shift); score_clockevent.max_delta_ns = clockevent_delta2ns((u32)~0, &score_clockevent); + score_clockevent.max_delta_ticks = (u32)~0; score_clockevent.min_delta_ns = clockevent_delta2ns(50, &score_clockevent) + 1; + score_clockevent.min_delta_ticks = 50; score_clockevent.cpumask = cpumask_of(0); clockevents_register_device(&score_clockevent); } diff --git a/arch/score/kernel/traps.c b/arch/score/kernel/traps.c index e359ec675869..12daf45369b4 100644 --- a/arch/score/kernel/traps.c +++ b/arch/score/kernel/traps.c @@ -24,6 +24,7 @@ */ #include <linux/extable.h> +#include <linux/ptrace.h> #include <linux/sched/mm.h> #include <linux/sched/signal.h> #include <linux/sched/debug.h> diff --git a/arch/score/mm/extable.c b/arch/score/mm/extable.c index ec871355fc2d..6736a3ad6286 100644 --- a/arch/score/mm/extable.c +++ b/arch/score/mm/extable.c @@ -24,6 +24,8 @@ */ #include <linux/extable.h> +#include <linux/ptrace.h> +#include <asm/extable.h> int fixup_exception(struct pt_regs *regs) { diff --git a/arch/sh/boards/mach-cayman/setup.c b/arch/sh/boards/mach-cayman/setup.c index 340fd40b381d..9c292c27e0d7 100644 --- a/arch/sh/boards/mach-cayman/setup.c +++ b/arch/sh/boards/mach-cayman/setup.c @@ -128,7 +128,6 @@ static int __init smsc_superio_setup(void) SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX); SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX); -#ifdef CONFIG_IDE /* * Only IDE1 exists on the Cayman */ @@ -158,7 +157,6 @@ static int __init smsc_superio_setup(void) SMSC_SUPERIO_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */ SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */ SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */ -#endif /* Exit the configuration state */ outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h index dcf278075429..1b77f068be2b 100644 --- a/arch/sh/include/asm/bug.h +++ b/arch/sh/include/asm/bug.h @@ -50,7 +50,7 @@ do { \ "i" (sizeof(struct bug_entry))); \ } while (0) -#define __WARN_TAINT(taint) \ +#define __WARN_FLAGS(flags) \ do { \ __asm__ __volatile__ ( \ "1:\t.short %O0\n" \ @@ -59,7 +59,7 @@ do { \ : "n" (TRAPA_BUG_OPCODE), \ "i" (__FILE__), \ "i" (__LINE__), \ - "i" (BUGFLAG_TAINT(taint)), \ + "i" (BUGFLAG_WARNING|(flags)), \ "i" (sizeof(struct bug_entry))); \ } while (0) diff --git a/arch/sh/include/asm/extable.h b/arch/sh/include/asm/extable.h new file mode 100644 index 000000000000..df2ee2fcb8d3 --- /dev/null +++ b/arch/sh/include/asm/extable.h @@ -0,0 +1,10 @@ +#ifndef __ASM_SH_EXTABLE_H +#define __ASM_SH_EXTABLE_H + +#include <asm-generic/extable.h> + +#if defined(CONFIG_SUPERH64) && defined(CONFIG_MMU) +#define ARCH_HAS_SEARCH_EXTABLE +#endif + +#endif diff --git a/arch/sh/include/asm/pgtable-2level.h b/arch/sh/include/asm/pgtable-2level.h index 19bd89db17e7..f75cf4387257 100644 --- a/arch/sh/include/asm/pgtable-2level.h +++ b/arch/sh/include/asm/pgtable-2level.h @@ -1,6 +1,7 @@ #ifndef __ASM_SH_PGTABLE_2LEVEL_H #define __ASM_SH_PGTABLE_2LEVEL_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> /* diff --git a/arch/sh/include/asm/pgtable-3level.h b/arch/sh/include/asm/pgtable-3level.h index 249a985d9648..9b1e776eca31 100644 --- a/arch/sh/include/asm/pgtable-3level.h +++ b/arch/sh/include/asm/pgtable-3level.h @@ -1,6 +1,7 @@ #ifndef __ASM_SH_PGTABLE_3LEVEL_H #define __ASM_SH_PGTABLE_3LEVEL_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> /* diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h index c4f0fee812c3..2722b61b2283 100644 --- a/arch/sh/include/asm/uaccess.h +++ b/arch/sh/include/asm/uaccess.h @@ -1,12 +1,8 @@ #ifndef __ASM_SH_UACCESS_H #define __ASM_SH_UACCESS_H -#include <linux/errno.h> -#include <linux/sched.h> #include <asm/segment.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 +#include <asm/extable.h> #define __addr_ok(addr) \ ((unsigned long __force)(addr) < current_thread_info()->addr_limit.seg) @@ -112,19 +108,18 @@ extern __must_check long strnlen_user(const char __user *str, long n); __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); static __always_inline unsigned long -__copy_from_user(void *to, const void __user *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { return __copy_user(to, (__force void *)from, n); } static __always_inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { return __copy_user((__force void *)to, from, n); } - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * Clear the area and return remaining number of bytes @@ -144,55 +139,6 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size); __cl_size; \ }) -static inline unsigned long -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - unsigned long __copy_from = (unsigned long) from; - __kernel_size_t __copy_size = (__kernel_size_t) n; - - if (__copy_size && __access_ok(__copy_from, __copy_size)) - __copy_size = __copy_user(to, from, __copy_size); - - if (unlikely(__copy_size)) - memset(to + (n - __copy_size), 0, __copy_size); - - return __copy_size; -} - -static inline unsigned long -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - unsigned long __copy_to = (unsigned long) to; - __kernel_size_t __copy_size = (__kernel_size_t) n; - - if (__copy_size && __access_ok(__copy_to, __copy_size)) - return __copy_user(to, from, __copy_size); - - return __copy_size; -} - -/* - * 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; -}; - -#if defined(CONFIG_SUPERH64) && defined(CONFIG_MMU) -#define ARCH_HAS_SEARCH_EXTABLE -#endif - -int fixup_exception(struct pt_regs *regs); - extern void *set_exception_table_vec(unsigned int vec, void *handler); static inline void *set_exception_table_evt(unsigned int evt, void *handler) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 68ac5c7cd982..58243b0d21c0 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -31,7 +31,8 @@ config SPARC select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_PCI_IOMAP select HAVE_NMI_WATCHDOG if SPARC64 - select HAVE_CBPF_JIT + select HAVE_CBPF_JIT if SPARC32 + select HAVE_EBPF_JIT if SPARC64 select HAVE_DEBUG_BUGVERBOSE select GENERIC_SMP_IDLE_THREAD select GENERIC_CLOCKEVENTS @@ -42,8 +43,7 @@ config SPARC select OLD_SIGSUSPEND select ARCH_HAS_SG_CHAIN select CPU_NO_EFFICIENT_FFS - select HAVE_ARCH_HARDENED_USERCOPY - select PROVE_LOCKING_SMALL if PROVE_LOCKING + select LOCKDEP_SMALL if LOCKDEP select ARCH_WANT_RELAX_ORDER config SPARC32 @@ -82,6 +82,7 @@ config SPARC64 select HAVE_ARCH_AUDITSYSCALL select ARCH_SUPPORTS_ATOMIC_RMW select HAVE_NMI + select HAVE_REGS_AND_STACK_ACCESS_API config ARCH_DEFCONFIG string diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index f294dd42fc7d..5961b2d8398a 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h @@ -17,6 +17,7 @@ #define HPAGE_SHIFT 23 #define REAL_HPAGE_SHIFT 22 +#define HPAGE_2GB_SHIFT 31 #define HPAGE_256MB_SHIFT 28 #define HPAGE_64K_SHIFT 16 #define REAL_HPAGE_SIZE (_AC(1,UL) << REAL_HPAGE_SHIFT) @@ -27,7 +28,7 @@ #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA #define REAL_HPAGE_PER_HPAGE (_AC(1,UL) << (HPAGE_SHIFT - REAL_HPAGE_SHIFT)) -#define HUGE_MAX_HSTATE 3 +#define HUGE_MAX_HSTATE 4 #endif #ifndef __ASSEMBLY__ diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 56e49c8f770d..6fbd931f0570 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -12,6 +12,7 @@ * the SpitFire page tables. */ +#include <asm-generic/5level-fixup.h> #include <linux/compiler.h> #include <linux/const.h> #include <asm/types.h> @@ -678,26 +679,27 @@ static inline unsigned long pmd_pfn(pmd_t pmd) return pte_pfn(pte); } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -static inline unsigned long pmd_dirty(pmd_t pmd) +#define __HAVE_ARCH_PMD_WRITE +static inline unsigned long pmd_write(pmd_t pmd) { pte_t pte = __pte(pmd_val(pmd)); - return pte_dirty(pte); + return pte_write(pte); } -static inline unsigned long pmd_young(pmd_t pmd) +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline unsigned long pmd_dirty(pmd_t pmd) { pte_t pte = __pte(pmd_val(pmd)); - return pte_young(pte); + return pte_dirty(pte); } -static inline unsigned long pmd_write(pmd_t pmd) +static inline unsigned long pmd_young(pmd_t pmd) { pte_t pte = __pte(pmd_val(pmd)); - return pte_write(pte); + return pte_young(pte); } static inline unsigned long pmd_trans_huge(pmd_t pmd) diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h index 365d4cb267b4..dd27159819eb 100644 --- a/arch/sparc/include/asm/processor_32.h +++ b/arch/sparc/include/asm/processor_32.h @@ -18,12 +18,6 @@ #include <asm/signal.h> #include <asm/page.h> -/* - * The sparc has no problems with write protection - */ -#define wp_works_ok 1 -#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ - /* Whee, this is STACK_TOP + PAGE_SIZE and the lowest kernel address too... * That one page is used to protect kernel from intruders, so that * we can make our access_ok test faster diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h index 6448cfc8292f..b58ee9018433 100644 --- a/arch/sparc/include/asm/processor_64.h +++ b/arch/sparc/include/asm/processor_64.h @@ -18,10 +18,6 @@ #include <asm/ptrace.h> #include <asm/page.h> -/* The sparc has no problems with write protection */ -#define wp_works_ok 1 -#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ - /* * User lives in his very own context, and cannot reference us. Note * that TASK_SIZE is a misnomer, it really gives maximum user virtual diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h index ca57f08bd3db..d73428e4333c 100644 --- a/arch/sparc/include/asm/ptrace.h +++ b/arch/sparc/include/asm/ptrace.h @@ -83,7 +83,8 @@ unsigned long profile_pc(struct pt_regs *); #define MAX_REG_OFFSET (offsetof(struct pt_regs, magic)) -extern int regs_query_register_offset(const char *name); +int regs_query_register_offset(const char *name); +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); /** * regs_get_register() - get register value from its offset diff --git a/arch/sparc/include/asm/uaccess.h b/arch/sparc/include/asm/uaccess.h index bd56c28fff9f..9e068bf9060a 100644 --- a/arch/sparc/include/asm/uaccess.h +++ b/arch/sparc/include/asm/uaccess.h @@ -7,7 +7,7 @@ #endif #define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) + (uaccess_kernel() ? ~0UL : TASK_SIZE) long strncpy_from_user(char *dest, const char __user *src, long count); diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index ea55f86d7ccd..12ebee2d97c7 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h @@ -7,14 +7,8 @@ #ifndef _ASM_UACCESS_H #define _ASM_UACCESS_H -#ifdef __KERNEL__ #include <linux/compiler.h> -#include <linux/sched.h> #include <linux/string.h> -#include <linux/errno.h> -#endif - -#ifndef __ASSEMBLY__ #include <asm/processor.h> @@ -30,9 +24,6 @@ #define KERNEL_DS ((mm_segment_t) { 0 }) #define USER_DS ((mm_segment_t) { -1 }) -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define get_ds() (KERNEL_DS) #define get_fs() (current->thread.current_ds) #define set_fs(val) ((current->thread.current_ds) = (val)) @@ -45,7 +36,7 @@ * large size and address near to PAGE_OFFSET - a fault will break his intentions. */ #define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; }) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) +#define __kernel_ok (uaccess_kernel()) #define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size))) #define access_ok(type, addr, size) \ ({ (void)(type); __access_ok((unsigned long)(addr), size); }) @@ -80,8 +71,6 @@ struct exception_table_entry /* Returns 0 if exception not found and fixup otherwise. */ unsigned long search_extables_range(unsigned long addr, unsigned long *g2); -void __ret_efault(void); - /* Uh, these should become the main single-value transfer routines.. * They automatically use the right size if we just have the right * pointer type.. @@ -246,39 +235,18 @@ int __get_user_bad(void); unsigned long __copy_user(void __user *to, const void __user *from, unsigned long size); -static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) -{ - if (n && __access_ok((unsigned long) to, n)) { - check_object_size(from, n, true); - return __copy_user(to, (__force void __user *) from, n); - } else - return n; -} - -static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) +static inline unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - check_object_size(from, n, true); return __copy_user(to, (__force void __user *) from, n); } -static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (n && __access_ok((unsigned long) from, n)) { - check_object_size(to, n, false); - return __copy_user((__force void __user *) to, from, n); - } else { - memset(to, 0, n); - return n; - } -} - -static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) +static inline unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n) { return __copy_user((__force void __user *) to, from, n); } -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER static inline unsigned long __clear_user(void __user *addr, unsigned long size) { @@ -312,6 +280,4 @@ static inline unsigned long clear_user(void __user *addr, unsigned long n) __must_check long strlen_user(const char __user *str); __must_check long strnlen_user(const char __user *str, long n); -#endif /* __ASSEMBLY__ */ - #endif /* _ASM_UACCESS_H */ diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index 5373136c412b..6096d671aa63 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -5,18 +5,12 @@ * User space memory access functions */ -#ifdef __KERNEL__ -#include <linux/errno.h> #include <linux/compiler.h> #include <linux/string.h> -#include <linux/thread_info.h> #include <asm/asi.h> #include <asm/spitfire.h> #include <asm-generic/uaccess-unaligned.h> #include <asm/extable_64.h> -#endif - -#ifndef __ASSEMBLY__ #include <asm/processor.h> @@ -36,9 +30,6 @@ #define KERNEL_DS ((mm_segment_t) { ASI_P }) #define USER_DS ((mm_segment_t) { ASI_AIUS }) /* har har har */ -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)}) #define get_ds() (KERNEL_DS) @@ -185,39 +176,19 @@ __asm__ __volatile__( \ int __get_user_bad(void); -unsigned long __must_check ___copy_from_user(void *to, +unsigned long __must_check raw_copy_from_user(void *to, const void __user *from, unsigned long size); -static inline unsigned long __must_check -copy_from_user(void *to, const void __user *from, unsigned long size) -{ - check_object_size(to, size, false); - return ___copy_from_user(to, from, size); -} -#define __copy_from_user copy_from_user - -unsigned long __must_check ___copy_to_user(void __user *to, +unsigned long __must_check raw_copy_to_user(void __user *to, const void *from, unsigned long size); -static inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long size) -{ - check_object_size(from, size, true); +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER - return ___copy_to_user(to, from, size); -} -#define __copy_to_user copy_to_user - -unsigned long __must_check ___copy_in_user(void __user *to, +unsigned long __must_check raw_copy_in_user(void __user *to, const void __user *from, unsigned long size); -static inline unsigned long __must_check -copy_in_user(void __user *to, void __user *from, unsigned long size) -{ - return ___copy_in_user(to, from, size); -} -#define __copy_in_user copy_in_user unsigned long __must_check __clear_user(void __user *, unsigned long); @@ -226,14 +197,9 @@ unsigned long __must_check __clear_user(void __user *, unsigned long); __must_check long strlen_user(const char __user *str); __must_check long strnlen_user(const char __user *str, long n); -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - struct pt_regs; unsigned long compute_effective_address(struct pt_regs *, unsigned int insn, unsigned int rd); -#endif /* __ASSEMBLY__ */ - #endif /* _ASM_UACCESS_H */ diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index a25dc32f5d6a..3f4ad19d9ec7 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -88,6 +88,12 @@ #define SCM_TIMESTAMPING_OPT_STATS 0x0038 +#define SO_MEMINFO 0x0039 + +#define SO_INCOMING_NAPI_ID 0x003a + +#define SO_COOKIE 0x003b + /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index 36eee8132c22..ae77df75bffa 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -425,8 +425,9 @@ #define __NR_copy_file_range 357 #define __NR_preadv2 358 #define __NR_pwritev2 359 +#define __NR_statx 360 -#define NR_syscalls 360 +#define NR_syscalls 361 /* Bitmask values returned from kern_features system call. */ #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 @@ -442,4 +443,9 @@ #define __IGNORE_getresgid #endif +/* Sparc doesn't have protection keys. */ +#define __IGNORE_pkey_mprotect +#define __IGNORE_pkey_alloc +#define __IGNORE_pkey_free + #endif /* _UAPI_SPARC_UNISTD_H */ diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 7bb317b87dde..7274e43ff9be 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S @@ -809,10 +809,3 @@ lvl14_save: .word 0 .word 0 .word t_irq14 - - .section ".fixup",#alloc,#execinstr - .globl __ret_efault -__ret_efault: - ret - restore %g0, -EFAULT, %o0 -EXPORT_SYMBOL(__ret_efault) diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index 6aa3da152c20..44101196d02b 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -96,6 +96,7 @@ sparc64_boot: andn %g1, PSTATE_AM, %g1 wrpr %g1, 0x0, %pstate ba,a,pt %xcc, 1f + nop .globl prom_finddev_name, prom_chosen_path, prom_root_node .globl prom_getprop_name, prom_mmu_name, prom_peer_name @@ -613,6 +614,7 @@ niagara_tlb_fixup: nop ba,a,pt %xcc, 80f + nop niagara4_patch: call niagara4_patch_copyops nop @@ -622,6 +624,7 @@ niagara4_patch: nop ba,a,pt %xcc, 80f + nop niagara2_patch: call niagara2_patch_copyops @@ -632,6 +635,7 @@ niagara2_patch: nop ba,a,pt %xcc, 80f + nop niagara_patch: call niagara_patch_copyops diff --git a/arch/sparc/kernel/misctrap.S b/arch/sparc/kernel/misctrap.S index 34b4933900bf..9276d2f0dd86 100644 --- a/arch/sparc/kernel/misctrap.S +++ b/arch/sparc/kernel/misctrap.S @@ -82,6 +82,7 @@ do_stdfmna: call handle_stdfmna add %sp, PTREGS_OFF, %o0 ba,a,pt %xcc, rtrap + nop .size do_stdfmna,.-do_stdfmna .type breakpoint_trap,#function diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index df9e731a76f5..e1d965e90e16 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -351,7 +351,7 @@ static int genregs64_set(struct task_struct *target, } if (!ret) { - unsigned long y; + unsigned long y = regs->y; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &y, @@ -1162,3 +1162,39 @@ int regs_query_register_offset(const char *name) return roff->offset; return -EINVAL; } + +/** + * regs_within_kernel_stack() - check the address in the stack + * @regs: pt_regs which contains kernel stack pointer. + * @addr: address which is checked. + * + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). + * If @addr is within the kernel stack, it returns true. If not, returns false. + */ +static inline int regs_within_kernel_stack(struct pt_regs *regs, + unsigned long addr) +{ + unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS; + return ((addr & ~(THREAD_SIZE - 1)) == + (ksp & ~(THREAD_SIZE - 1))); +} + +/** + * regs_get_kernel_stack_nth() - get Nth entry of the stack + * @regs: pt_regs which contains kernel stack pointer. + * @n: stack entry number. + * + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which + * is specified by @regs. If the @n th entry is NOT in the kernel stack, + * this returns 0. + */ +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) +{ + unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS; + unsigned long *addr = (unsigned long *)ksp; + addr += n; + if (regs_within_kernel_stack(regs, (unsigned long)addr)) + return *addr; + else + return 0; +} diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 216948ca4382..709a82ebd294 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -237,6 +237,7 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 bne,pt %xcc, user_rtt_fill_32bit wrpr %g1, %cwp ba,a,pt %xcc, user_rtt_fill_64bit + nop user_rtt_fill_fixup_dax: ba,pt %xcc, user_rtt_fill_fixup_common diff --git a/arch/sparc/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S index 4a73009f66a5..d7e540842809 100644 --- a/arch/sparc/kernel/spiterrs.S +++ b/arch/sparc/kernel/spiterrs.S @@ -86,6 +86,7 @@ __spitfire_cee_trap_continue: rd %pc, %g7 ba,a,pt %xcc, 2f + nop 1: ba,pt %xcc, etrap_irq rd %pc, %g7 diff --git a/arch/sparc/kernel/sun4v_tlb_miss.S b/arch/sparc/kernel/sun4v_tlb_miss.S index 6179e19bc9b9..c19f352f46c7 100644 --- a/arch/sparc/kernel/sun4v_tlb_miss.S +++ b/arch/sparc/kernel/sun4v_tlb_miss.S @@ -352,6 +352,7 @@ sun4v_mna: call sun4v_do_mna add %sp, PTREGS_OFF, %o0 ba,a,pt %xcc, rtrap + nop /* Privileged Action. */ sun4v_privact: diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index d63fc613e7a9..5fd352b759af 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -98,27 +98,7 @@ static struct attribute_group mmu_stat_group = { .name = "mmu_stats", }; -/* XXX convert to rusty's on_one_cpu */ -static unsigned long run_on_cpu(unsigned long cpu, - unsigned long (*func)(unsigned long), - unsigned long arg) -{ - cpumask_t old_affinity; - unsigned long ret; - - cpumask_copy(&old_affinity, ¤t->cpus_allowed); - /* should return -EINVAL to userspace */ - if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) - return 0; - - ret = func(arg); - - set_cpus_allowed_ptr(current, &old_affinity); - - return ret; -} - -static unsigned long read_mmustat_enable(unsigned long junk) +static long read_mmustat_enable(void *data __maybe_unused) { unsigned long ra = 0; @@ -127,11 +107,11 @@ static unsigned long read_mmustat_enable(unsigned long junk) return ra != 0; } -static unsigned long write_mmustat_enable(unsigned long val) +static long write_mmustat_enable(void *data) { - unsigned long ra, orig_ra; + unsigned long ra, orig_ra, *val = data; - if (val) + if (*val) ra = __pa(&per_cpu(mmu_stats, smp_processor_id())); else ra = 0UL; @@ -142,7 +122,8 @@ static unsigned long write_mmustat_enable(unsigned long val) static ssize_t show_mmustat_enable(struct device *s, struct device_attribute *attr, char *buf) { - unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0); + long val = work_on_cpu(s->id, read_mmustat_enable, NULL); + return sprintf(buf, "%lx\n", val); } @@ -150,13 +131,15 @@ static ssize_t store_mmustat_enable(struct device *s, struct device_attribute *attr, const char *buf, size_t count) { - unsigned long val, err; - int ret = sscanf(buf, "%lu", &val); + unsigned long val; + long err; + int ret; + ret = sscanf(buf, "%lu", &val); if (ret != 1) return -EINVAL; - err = run_on_cpu(s->id, write_mmustat_enable, val); + err = work_on_cpu(s->id, write_mmustat_enable, &val); if (err) return -EIO; diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index eac7f0db5c8c..5253e895b81b 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -89,3 +89,4 @@ sys_call_table: /*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf /*350*/ .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen /*355*/ .long sys_setsockopt, sys_mlock2, sys_copy_file_range, sys_preadv2, sys_pwritev2 +/*360*/ .long sys_statx diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index b0f17ff2ddba..82339f6be0b2 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -90,6 +90,7 @@ sys_call_table32: .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf /*350*/ .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen .word compat_sys_setsockopt, sys_mlock2, sys_copy_file_range, compat_sys_preadv2, compat_sys_pwritev2 +/*360*/ .word sys_statx #endif /* CONFIG_COMPAT */ @@ -171,3 +172,4 @@ sys_call_table: .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf /*350*/ .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen .word sys_setsockopt, sys_mlock2, sys_copy_file_range, sys_preadv2, sys_pwritev2 +/*360*/ .word sys_statx diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 244062bdaa56..9f575dfc2e41 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -228,7 +228,9 @@ void register_percpu_ce(int cpu) ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, ce->shift); ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce); + ce->max_delta_ticks = (unsigned long)sparc_config.clock_rate; ce->min_delta_ns = clockevent_delta2ns(100, ce); + ce->min_delta_ticks = 100; clockevents_register_device(ce); } diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 12a6d3555cb8..98d05de8da66 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -796,8 +796,10 @@ void __init time_init(void) sparc64_clockevent.max_delta_ns = clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); + sparc64_clockevent.max_delta_ticks = 0x7fffffffffffffffUL; sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); + sparc64_clockevent.min_delta_ticks = 0xF; printk("clockevent: mult[%x] shift[%d]\n", sparc64_clockevent.mult, sparc64_clockevent.shift); diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S index 5604a2b051d4..364af3250646 100644 --- a/arch/sparc/kernel/urtt_fill.S +++ b/arch/sparc/kernel/urtt_fill.S @@ -92,6 +92,7 @@ user_rtt_fill_fixup_common: call sun4v_data_access_exception nop ba,a,pt %xcc, rtrap + nop 1: call spitfire_data_access_exception nop diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S index 855019a8590e..1ee173cc3c39 100644 --- a/arch/sparc/kernel/winfixup.S +++ b/arch/sparc/kernel/winfixup.S @@ -152,6 +152,8 @@ fill_fixup_dax: call sun4v_data_access_exception nop ba,a,pt %xcc, rtrap + nop 1: call spitfire_data_access_exception nop ba,a,pt %xcc, rtrap + nop diff --git a/arch/sparc/lib/GENcopy_from_user.S b/arch/sparc/lib/GENcopy_from_user.S index 69a439fa2fc1..8aa16ef113f2 100644 --- a/arch/sparc/lib/GENcopy_from_user.S +++ b/arch/sparc/lib/GENcopy_from_user.S @@ -23,7 +23,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/GENcopy_to_user.S b/arch/sparc/lib/GENcopy_to_user.S index 9947427ce354..311c8fa5e98e 100644 --- a/arch/sparc/lib/GENcopy_to_user.S +++ b/arch/sparc/lib/GENcopy_to_user.S @@ -27,7 +27,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/GENpatch.S b/arch/sparc/lib/GENpatch.S index fab9e89f16bd..95e2f1f9e477 100644 --- a/arch/sparc/lib/GENpatch.S +++ b/arch/sparc/lib/GENpatch.S @@ -26,8 +26,8 @@ .type generic_patch_copyops,#function generic_patch_copyops: GEN_DO_PATCH(memcpy, GENmemcpy) - GEN_DO_PATCH(___copy_from_user, GENcopy_from_user) - GEN_DO_PATCH(___copy_to_user, GENcopy_to_user) + GEN_DO_PATCH(raw_copy_from_user, GENcopy_from_user) + GEN_DO_PATCH(raw_copy_to_user, GENcopy_to_user) retl nop .size generic_patch_copyops,.-generic_patch_copyops diff --git a/arch/sparc/lib/NG2copy_from_user.S b/arch/sparc/lib/NG2copy_from_user.S index b79a6998d87c..0d8a018118c2 100644 --- a/arch/sparc/lib/NG2copy_from_user.S +++ b/arch/sparc/lib/NG2copy_from_user.S @@ -36,7 +36,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/NG2copy_to_user.S b/arch/sparc/lib/NG2copy_to_user.S index dcec55f254ab..a7a0ea0d8a0b 100644 --- a/arch/sparc/lib/NG2copy_to_user.S +++ b/arch/sparc/lib/NG2copy_to_user.S @@ -45,7 +45,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S index c629dbd121b6..64dcd6cdb606 100644 --- a/arch/sparc/lib/NG2memcpy.S +++ b/arch/sparc/lib/NG2memcpy.S @@ -326,11 +326,13 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ blu 170f nop ba,a,pt %xcc, 180f + nop 4: /* 32 <= low bits < 48 */ blu 150f nop ba,a,pt %xcc, 160f + nop 5: /* 0 < low bits < 32 */ blu,a 6f cmp %g2, 8 @@ -338,6 +340,7 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ blu 130f nop ba,a,pt %xcc, 140f + nop 6: /* 0 < low bits < 16 */ bgeu 120f nop @@ -475,6 +478,7 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ brz,pt %o2, 85f sub %o0, %o1, GLOBAL_SPARE ba,a,pt %XCC, 90f + nop .align 64 75: /* 16 < len <= 64 */ diff --git a/arch/sparc/lib/NG2patch.S b/arch/sparc/lib/NG2patch.S index 28c36f06a6d1..56ccc19adde8 100644 --- a/arch/sparc/lib/NG2patch.S +++ b/arch/sparc/lib/NG2patch.S @@ -26,8 +26,8 @@ .type niagara2_patch_copyops,#function niagara2_patch_copyops: NG_DO_PATCH(memcpy, NG2memcpy) - NG_DO_PATCH(___copy_from_user, NG2copy_from_user) - NG_DO_PATCH(___copy_to_user, NG2copy_to_user) + NG_DO_PATCH(raw_copy_from_user, NG2copy_from_user) + NG_DO_PATCH(raw_copy_to_user, NG2copy_to_user) retl nop .size niagara2_patch_copyops,.-niagara2_patch_copyops diff --git a/arch/sparc/lib/NG4copy_from_user.S b/arch/sparc/lib/NG4copy_from_user.S index 16a286c1a528..5bb506bd61fa 100644 --- a/arch/sparc/lib/NG4copy_from_user.S +++ b/arch/sparc/lib/NG4copy_from_user.S @@ -31,7 +31,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/NG4copy_to_user.S b/arch/sparc/lib/NG4copy_to_user.S index 6b0276ffc858..a82d4d45fc1c 100644 --- a/arch/sparc/lib/NG4copy_to_user.S +++ b/arch/sparc/lib/NG4copy_to_user.S @@ -40,7 +40,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S index 75bb93b1437f..78ea962edcbe 100644 --- a/arch/sparc/lib/NG4memcpy.S +++ b/arch/sparc/lib/NG4memcpy.S @@ -530,4 +530,5 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ bne,pt %icc, 1b EX_ST(STORE(stb, %g1, %o0 - 0x01), NG4_retl_o2_plus_1) ba,a,pt %icc, .Lexit + nop .size FUNC_NAME, .-FUNC_NAME diff --git a/arch/sparc/lib/NG4memset.S b/arch/sparc/lib/NG4memset.S index 41da4bdd95cb..7c0c81f18837 100644 --- a/arch/sparc/lib/NG4memset.S +++ b/arch/sparc/lib/NG4memset.S @@ -102,4 +102,5 @@ NG4bzero: bne,pt %icc, 1b add %o0, 0x30, %o0 ba,a,pt %icc, .Lpostloop + nop .size NG4bzero,.-NG4bzero diff --git a/arch/sparc/lib/NG4patch.S b/arch/sparc/lib/NG4patch.S index a114cbcf2a48..3cc0f8cc95df 100644 --- a/arch/sparc/lib/NG4patch.S +++ b/arch/sparc/lib/NG4patch.S @@ -26,8 +26,8 @@ .type niagara4_patch_copyops,#function niagara4_patch_copyops: NG_DO_PATCH(memcpy, NG4memcpy) - NG_DO_PATCH(___copy_from_user, NG4copy_from_user) - NG_DO_PATCH(___copy_to_user, NG4copy_to_user) + NG_DO_PATCH(raw_copy_from_user, NG4copy_from_user) + NG_DO_PATCH(raw_copy_to_user, NG4copy_to_user) retl nop .size niagara4_patch_copyops,.-niagara4_patch_copyops diff --git a/arch/sparc/lib/NGcopy_from_user.S b/arch/sparc/lib/NGcopy_from_user.S index 9cd42fcbc781..2333b6f3e824 100644 --- a/arch/sparc/lib/NGcopy_from_user.S +++ b/arch/sparc/lib/NGcopy_from_user.S @@ -25,7 +25,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/NGcopy_to_user.S b/arch/sparc/lib/NGcopy_to_user.S index 5c358afd464e..07ba20bc4ea4 100644 --- a/arch/sparc/lib/NGcopy_to_user.S +++ b/arch/sparc/lib/NGcopy_to_user.S @@ -28,7 +28,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop #endif diff --git a/arch/sparc/lib/NGmemcpy.S b/arch/sparc/lib/NGmemcpy.S index d88c4ed50a00..cd654a719b27 100644 --- a/arch/sparc/lib/NGmemcpy.S +++ b/arch/sparc/lib/NGmemcpy.S @@ -394,6 +394,7 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ brz,pt %i2, 85f sub %o0, %i1, %i3 ba,a,pt %XCC, 90f + nop .align 64 70: /* 16 < len <= 64 */ diff --git a/arch/sparc/lib/NGpatch.S b/arch/sparc/lib/NGpatch.S index 3b0674fc3366..62ccda7e7b38 100644 --- a/arch/sparc/lib/NGpatch.S +++ b/arch/sparc/lib/NGpatch.S @@ -26,8 +26,8 @@ .type niagara_patch_copyops,#function niagara_patch_copyops: NG_DO_PATCH(memcpy, NGmemcpy) - NG_DO_PATCH(___copy_from_user, NGcopy_from_user) - NG_DO_PATCH(___copy_to_user, NGcopy_to_user) + NG_DO_PATCH(raw_copy_from_user, NGcopy_from_user) + NG_DO_PATCH(raw_copy_to_user, NGcopy_to_user) retl nop .size niagara_patch_copyops,.-niagara_patch_copyops diff --git a/arch/sparc/lib/U1copy_from_user.S b/arch/sparc/lib/U1copy_from_user.S index bb6ff73229e3..9a6e68a9bf4a 100644 --- a/arch/sparc/lib/U1copy_from_user.S +++ b/arch/sparc/lib/U1copy_from_user.S @@ -19,7 +19,7 @@ .text; \ .align 4; -#define FUNC_NAME ___copy_from_user +#define FUNC_NAME raw_copy_from_user #define LOAD(type,addr,dest) type##a [addr] %asi, dest #define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_AIUS, dest #define EX_RETVAL(x) 0 @@ -31,7 +31,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop; \ #include "U1memcpy.S" diff --git a/arch/sparc/lib/U1copy_to_user.S b/arch/sparc/lib/U1copy_to_user.S index ed92ce739558..d7b28491eddf 100644 --- a/arch/sparc/lib/U1copy_to_user.S +++ b/arch/sparc/lib/U1copy_to_user.S @@ -19,7 +19,7 @@ .text; \ .align 4; -#define FUNC_NAME ___copy_to_user +#define FUNC_NAME raw_copy_to_user #define STORE(type,src,addr) type##a src, [addr] ASI_AIUS #define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS #define EX_RETVAL(x) 0 @@ -31,7 +31,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop; \ #include "U1memcpy.S" diff --git a/arch/sparc/lib/U3copy_to_user.S b/arch/sparc/lib/U3copy_to_user.S index c4ee858e352a..f48fb87fe9f2 100644 --- a/arch/sparc/lib/U3copy_to_user.S +++ b/arch/sparc/lib/U3copy_to_user.S @@ -31,7 +31,7 @@ #define PREAMBLE \ rd %asi, %g1; \ cmp %g1, ASI_AIUS; \ - bne,pn %icc, ___copy_in_user; \ + bne,pn %icc, raw_copy_in_user; \ nop; \ #include "U3memcpy.S" diff --git a/arch/sparc/lib/U3patch.S b/arch/sparc/lib/U3patch.S index ecc302619a6e..91cd6539b6e1 100644 --- a/arch/sparc/lib/U3patch.S +++ b/arch/sparc/lib/U3patch.S @@ -26,8 +26,8 @@ .type cheetah_patch_copyops,#function cheetah_patch_copyops: ULTRA3_DO_PATCH(memcpy, U3memcpy) - ULTRA3_DO_PATCH(___copy_from_user, U3copy_from_user) - ULTRA3_DO_PATCH(___copy_to_user, U3copy_to_user) + ULTRA3_DO_PATCH(raw_copy_from_user, U3copy_from_user) + ULTRA3_DO_PATCH(raw_copy_to_user, U3copy_to_user) retl nop .size cheetah_patch_copyops,.-cheetah_patch_copyops diff --git a/arch/sparc/lib/copy_in_user.S b/arch/sparc/lib/copy_in_user.S index 0252b218de45..1b73bb80aeb0 100644 --- a/arch/sparc/lib/copy_in_user.S +++ b/arch/sparc/lib/copy_in_user.S @@ -44,7 +44,7 @@ __retl_o2_plus_1: * to copy register windows around during thread cloning. */ -ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ +ENTRY(raw_copy_in_user) /* %o0=dst, %o1=src, %o2=len */ cmp %o2, 0 be,pn %XCC, 85f or %o0, %o1, %o3 @@ -105,5 +105,5 @@ ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ add %o0, 1, %o0 retl clr %o0 -ENDPROC(___copy_in_user) -EXPORT_SYMBOL(___copy_in_user) +ENDPROC(raw_copy_in_user) +EXPORT_SYMBOL(raw_copy_in_user) diff --git a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S index cea644dc67a6..bc243ee807cc 100644 --- a/arch/sparc/lib/copy_user.S +++ b/arch/sparc/lib/copy_user.S @@ -364,21 +364,7 @@ short_aligned_end: 97: mov %o2, %g3 fixupretl: - sethi %hi(PAGE_OFFSET), %g1 - cmp %o0, %g1 - blu 1f - cmp %o1, %g1 - bgeu 1f - ld [%g6 + TI_PREEMPT], %g1 - cmp %g1, 0 - bne 1f - nop - save %sp, -64, %sp - mov %i0, %o0 - call __bzero - mov %g3, %o1 - restore -1: retl + retl mov %g3, %o0 /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index 323bc6b6e3ad..7c29d38e6b99 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c @@ -143,6 +143,10 @@ static pte_t sun4v_hugepage_shift_to_tte(pte_t entry, unsigned int shift) pte_val(entry) = pte_val(entry) & ~_PAGE_SZALL_4V; switch (shift) { + case HPAGE_2GB_SHIFT: + hugepage_size = _PAGE_SZ2GB_4V; + pte_val(entry) |= _PAGE_PMD_HUGE; + break; case HPAGE_256MB_SHIFT: hugepage_size = _PAGE_SZ256MB_4V; pte_val(entry) |= _PAGE_PMD_HUGE; @@ -183,6 +187,9 @@ static unsigned int sun4v_huge_tte_to_shift(pte_t entry) unsigned int shift; switch (tte_szbits) { + case _PAGE_SZ2GB_4V: + shift = HPAGE_2GB_SHIFT; + break; case _PAGE_SZ256MB_4V: shift = HPAGE_256MB_SHIFT; break; @@ -261,7 +268,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, if (!pmd) return NULL; - if (sz == PMD_SHIFT) + if (sz >= PMD_SIZE) pte = (pte_t *)pmd; else pte = pte_alloc_map(mm, pmd, addr); @@ -454,6 +461,22 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, pgd_t *pgd; unsigned long next; + addr &= PMD_MASK; + if (addr < floor) { + addr += PMD_SIZE; + if (!addr) + return; + } + if (ceiling) { + ceiling &= PMD_MASK; + if (!ceiling) + return; + } + if (end - 1 > ceiling - 1) + end -= PMD_SIZE; + if (addr > end - 1) + return; + pgd = pgd_offset(tlb->mm, addr); do { next = pgd_addr_end(addr, end); diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index ccd455328989..0cda653ae007 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -337,6 +337,10 @@ static int __init setup_hugepagesz(char *string) hugepage_shift = ilog2(hugepage_size); switch (hugepage_shift) { + case HPAGE_2GB_SHIFT: + hv_pgsz_mask = HV_PGSZ_MASK_2GB; + hv_pgsz_idx = HV_PGSZ_IDX_2GB; + break; case HPAGE_256MB_SHIFT: hv_pgsz_mask = HV_PGSZ_MASK_256MB; hv_pgsz_idx = HV_PGSZ_IDX_256MB; @@ -1563,7 +1567,7 @@ bool kern_addr_valid(unsigned long addr) if ((long)addr < 0L) { unsigned long pa = __pa(addr); - if ((addr >> max_phys_bits) != 0UL) + if ((pa >> max_phys_bits) != 0UL) return false; return pfn_valid(pa >> PAGE_SHIFT); diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index def82f6d626f..8e76ebba2986 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -54,6 +54,7 @@ enum mbus_module srmmu_modtype; static unsigned int hwbug_bitmask; int vac_cache_size; +EXPORT_SYMBOL(vac_cache_size); int vac_line_size; extern struct resource sparc_iomap; diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index afda3bbf7854..ee8066c3d96c 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -154,7 +154,7 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, if (pte_val(*pte) & _PAGE_VALID) { bool exec = pte_exec(*pte); - tlb_batch_add_one(mm, vaddr, exec, false); + tlb_batch_add_one(mm, vaddr, exec, PAGE_SHIFT); } pte++; vaddr += PAGE_SIZE; @@ -209,9 +209,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, pte_t orig_pte = __pte(pmd_val(orig)); bool exec = pte_exec(orig_pte); - tlb_batch_add_one(mm, addr, exec, true); + tlb_batch_add_one(mm, addr, exec, REAL_HPAGE_SHIFT); tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec, - true); + REAL_HPAGE_SHIFT); } else { tlb_batch_pmd_scan(mm, addr, orig); } diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 0a04811f06b7..bedf08b22a47 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -122,7 +122,7 @@ void flush_tsb_user(struct tlb_batch *tb) spin_lock_irqsave(&mm->context.lock, flags); - if (tb->hugepage_shift < HPAGE_SHIFT) { + if (tb->hugepage_shift < REAL_HPAGE_SHIFT) { base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; if (tlb_type == cheetah_plus || tlb_type == hypervisor) @@ -155,7 +155,7 @@ void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, spin_lock_irqsave(&mm->context.lock, flags); - if (hugepage_shift < HPAGE_SHIFT) { + if (hugepage_shift < REAL_HPAGE_SHIFT) { base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; if (tlb_type == cheetah_plus || tlb_type == hypervisor) diff --git a/arch/sparc/net/Makefile b/arch/sparc/net/Makefile index 1306a58ac541..76fa8e95b721 100644 --- a/arch/sparc/net/Makefile +++ b/arch/sparc/net/Makefile @@ -1,4 +1,4 @@ # # Arch-specific network modules # -obj-$(CONFIG_BPF_JIT) += bpf_jit_asm.o bpf_jit_comp.o +obj-$(CONFIG_BPF_JIT) += bpf_jit_asm_$(BITS).o bpf_jit_comp_$(BITS).o diff --git a/arch/sparc/net/bpf_jit.h b/arch/sparc/net/bpf_jit_32.h index 33d6b375ff12..d5c069bff5f9 100644 --- a/arch/sparc/net/bpf_jit.h +++ b/arch/sparc/net/bpf_jit_32.h @@ -39,7 +39,7 @@ #define r_TMP2 G2 #define r_OFF G3 -/* assembly code in arch/sparc/net/bpf_jit_asm.S */ +/* assembly code in arch/sparc/net/bpf_jit_asm_32.S */ extern u32 bpf_jit_load_word[]; extern u32 bpf_jit_load_half[]; extern u32 bpf_jit_load_byte[]; diff --git a/arch/sparc/net/bpf_jit_64.h b/arch/sparc/net/bpf_jit_64.h new file mode 100644 index 000000000000..74abd45796ea --- /dev/null +++ b/arch/sparc/net/bpf_jit_64.h @@ -0,0 +1,66 @@ +#ifndef _BPF_JIT_H +#define _BPF_JIT_H + +#ifndef __ASSEMBLER__ +#define G0 0x00 +#define G1 0x01 +#define G2 0x02 +#define G3 0x03 +#define G6 0x06 +#define G7 0x07 +#define O0 0x08 +#define O1 0x09 +#define O2 0x0a +#define O3 0x0b +#define O4 0x0c +#define O5 0x0d +#define SP 0x0e +#define O7 0x0f +#define L0 0x10 +#define L1 0x11 +#define L2 0x12 +#define L3 0x13 +#define L4 0x14 +#define L5 0x15 +#define L6 0x16 +#define L7 0x17 +#define I0 0x18 +#define I1 0x19 +#define I2 0x1a +#define I3 0x1b +#define I4 0x1c +#define I5 0x1d +#define FP 0x1e +#define I7 0x1f + +#define r_SKB L0 +#define r_HEADLEN L4 +#define r_SKB_DATA L5 +#define r_TMP G1 +#define r_TMP2 G3 + +/* assembly code in arch/sparc/net/bpf_jit_asm_64.S */ +extern u32 bpf_jit_load_word[]; +extern u32 bpf_jit_load_half[]; +extern u32 bpf_jit_load_byte[]; +extern u32 bpf_jit_load_byte_msh[]; +extern u32 bpf_jit_load_word_positive_offset[]; +extern u32 bpf_jit_load_half_positive_offset[]; +extern u32 bpf_jit_load_byte_positive_offset[]; +extern u32 bpf_jit_load_byte_msh_positive_offset[]; +extern u32 bpf_jit_load_word_negative_offset[]; +extern u32 bpf_jit_load_half_negative_offset[]; +extern u32 bpf_jit_load_byte_negative_offset[]; +extern u32 bpf_jit_load_byte_msh_negative_offset[]; + +#else +#define r_RESULT %o0 +#define r_SKB %o0 +#define r_OFF %o1 +#define r_HEADLEN %l4 +#define r_SKB_DATA %l5 +#define r_TMP %g1 +#define r_TMP2 %g3 +#endif + +#endif /* _BPF_JIT_H */ diff --git a/arch/sparc/net/bpf_jit_asm.S b/arch/sparc/net/bpf_jit_asm_32.S index 8c83f4b8eb15..dcc402f5738a 100644 --- a/arch/sparc/net/bpf_jit_asm.S +++ b/arch/sparc/net/bpf_jit_asm_32.S @@ -1,18 +1,11 @@ #include <asm/ptrace.h> -#include "bpf_jit.h" +#include "bpf_jit_32.h" -#ifdef CONFIG_SPARC64 -#define SAVE_SZ 176 -#define SCRATCH_OFF STACK_BIAS + 128 -#define BE_PTR(label) be,pn %xcc, label -#define SIGN_EXTEND(reg) sra reg, 0, reg -#else #define SAVE_SZ 96 #define SCRATCH_OFF 72 #define BE_PTR(label) be label #define SIGN_EXTEND(reg) -#endif #define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */ diff --git a/arch/sparc/net/bpf_jit_asm_64.S b/arch/sparc/net/bpf_jit_asm_64.S new file mode 100644 index 000000000000..3b3f14655f81 --- /dev/null +++ b/arch/sparc/net/bpf_jit_asm_64.S @@ -0,0 +1,161 @@ +#include <asm/ptrace.h> + +#include "bpf_jit_64.h" + +#define SAVE_SZ 176 +#define SCRATCH_OFF STACK_BIAS + 128 +#define BE_PTR(label) be,pn %xcc, label +#define SIGN_EXTEND(reg) sra reg, 0, reg + +#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */ + + .text + .globl bpf_jit_load_word +bpf_jit_load_word: + cmp r_OFF, 0 + bl bpf_slow_path_word_neg + nop + .globl bpf_jit_load_word_positive_offset +bpf_jit_load_word_positive_offset: + sub r_HEADLEN, r_OFF, r_TMP + cmp r_TMP, 3 + ble bpf_slow_path_word + add r_SKB_DATA, r_OFF, r_TMP + andcc r_TMP, 3, %g0 + bne load_word_unaligned + nop + retl + ld [r_TMP], r_RESULT +load_word_unaligned: + ldub [r_TMP + 0x0], r_OFF + ldub [r_TMP + 0x1], r_TMP2 + sll r_OFF, 8, r_OFF + or r_OFF, r_TMP2, r_OFF + ldub [r_TMP + 0x2], r_TMP2 + sll r_OFF, 8, r_OFF + or r_OFF, r_TMP2, r_OFF + ldub [r_TMP + 0x3], r_TMP2 + sll r_OFF, 8, r_OFF + retl + or r_OFF, r_TMP2, r_RESULT + + .globl bpf_jit_load_half +bpf_jit_load_half: + cmp r_OFF, 0 + bl bpf_slow_path_half_neg + nop + .globl bpf_jit_load_half_positive_offset +bpf_jit_load_half_positive_offset: + sub r_HEADLEN, r_OFF, r_TMP + cmp r_TMP, 1 + ble bpf_slow_path_half + add r_SKB_DATA, r_OFF, r_TMP + andcc r_TMP, 1, %g0 + bne load_half_unaligned + nop + retl + lduh [r_TMP], r_RESULT +load_half_unaligned: + ldub [r_TMP + 0x0], r_OFF + ldub [r_TMP + 0x1], r_TMP2 + sll r_OFF, 8, r_OFF + retl + or r_OFF, r_TMP2, r_RESULT + + .globl bpf_jit_load_byte +bpf_jit_load_byte: + cmp r_OFF, 0 + bl bpf_slow_path_byte_neg + nop + .globl bpf_jit_load_byte_positive_offset +bpf_jit_load_byte_positive_offset: + cmp r_OFF, r_HEADLEN + bge bpf_slow_path_byte + nop + retl + ldub [r_SKB_DATA + r_OFF], r_RESULT + +#define bpf_slow_path_common(LEN) \ + save %sp, -SAVE_SZ, %sp; \ + mov %i0, %o0; \ + mov %i1, %o1; \ + add %fp, SCRATCH_OFF, %o2; \ + call skb_copy_bits; \ + mov (LEN), %o3; \ + cmp %o0, 0; \ + restore; + +bpf_slow_path_word: + bpf_slow_path_common(4) + bl bpf_error + ld [%sp + SCRATCH_OFF], r_RESULT + retl + nop +bpf_slow_path_half: + bpf_slow_path_common(2) + bl bpf_error + lduh [%sp + SCRATCH_OFF], r_RESULT + retl + nop +bpf_slow_path_byte: + bpf_slow_path_common(1) + bl bpf_error + ldub [%sp + SCRATCH_OFF], r_RESULT + retl + nop + +#define bpf_negative_common(LEN) \ + save %sp, -SAVE_SZ, %sp; \ + mov %i0, %o0; \ + mov %i1, %o1; \ + SIGN_EXTEND(%o1); \ + call bpf_internal_load_pointer_neg_helper; \ + mov (LEN), %o2; \ + mov %o0, r_TMP; \ + cmp %o0, 0; \ + BE_PTR(bpf_error); \ + restore; + +bpf_slow_path_word_neg: + sethi %hi(SKF_MAX_NEG_OFF), r_TMP + cmp r_OFF, r_TMP + bl bpf_error + nop + .globl bpf_jit_load_word_negative_offset +bpf_jit_load_word_negative_offset: + bpf_negative_common(4) + andcc r_TMP, 3, %g0 + bne load_word_unaligned + nop + retl + ld [r_TMP], r_RESULT + +bpf_slow_path_half_neg: + sethi %hi(SKF_MAX_NEG_OFF), r_TMP + cmp r_OFF, r_TMP + bl bpf_error + nop + .globl bpf_jit_load_half_negative_offset +bpf_jit_load_half_negative_offset: + bpf_negative_common(2) + andcc r_TMP, 1, %g0 + bne load_half_unaligned + nop + retl + lduh [r_TMP], r_RESULT + +bpf_slow_path_byte_neg: + sethi %hi(SKF_MAX_NEG_OFF), r_TMP + cmp r_OFF, r_TMP + bl bpf_error + nop + .globl bpf_jit_load_byte_negative_offset +bpf_jit_load_byte_negative_offset: + bpf_negative_common(1) + retl + ldub [r_TMP], r_RESULT + +bpf_error: + /* Make the JIT program itself return zero. */ + ret + restore %g0, %g0, %o0 diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp_32.c index a6d9204a6a0b..d193748548e2 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp_32.c @@ -8,7 +8,7 @@ #include <asm/cacheflush.h> #include <asm/ptrace.h> -#include "bpf_jit.h" +#include "bpf_jit_32.h" int bpf_jit_enable __read_mostly; @@ -17,24 +17,6 @@ static inline bool is_simm13(unsigned int value) return value + 0x1000 < 0x2000; } -static void bpf_flush_icache(void *start_, void *end_) -{ -#ifdef CONFIG_SPARC64 - /* Cheetah's I-cache is fully coherent. */ - if (tlb_type == spitfire) { - unsigned long start = (unsigned long) start_; - unsigned long end = (unsigned long) end_; - - start &= ~7UL; - end = (end + 7UL) & ~7UL; - while (start < end) { - flushi(start); - start += 32; - } - } -#endif -} - #define SEEN_DATAREF 1 /* might call external helpers */ #define SEEN_XREG 2 /* ebx is used */ #define SEEN_MEM 4 /* use mem[] for temporary storage */ @@ -82,11 +64,7 @@ static void bpf_flush_icache(void *start_, void *end_) #define BE (F2(0, 2) | CONDE) #define BNE (F2(0, 2) | CONDNE) -#ifdef CONFIG_SPARC64 -#define BE_PTR (F2(0, 1) | CONDE | (2 << 20)) -#else #define BE_PTR BE -#endif #define SETHI(K, REG) \ (F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff)) @@ -116,13 +94,8 @@ static void bpf_flush_icache(void *start_, void *end_) #define LD64 F3(3, 0x0b) #define ST32 F3(3, 0x04) -#ifdef CONFIG_SPARC64 -#define LDPTR LD64 -#define BASE_STACKFRAME 176 -#else #define LDPTR LD32 #define BASE_STACKFRAME 96 -#endif #define LD32I (LD32 | IMMED) #define LD8I (LD8 | IMMED) @@ -234,11 +207,7 @@ do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \ __emit_load8(BASE, STRUCT, FIELD, DEST); \ } while (0) -#ifdef CONFIG_SPARC64 -#define BIAS (STACK_BIAS - 4) -#else #define BIAS (-4) -#endif #define emit_ldmem(OFF, DEST) \ do { *prog++ = LD32I | RS1(SP) | S13(BIAS - (OFF)) | RD(DEST); \ @@ -249,13 +218,8 @@ do { *prog++ = ST32I | RS1(SP) | S13(BIAS - (OFF)) | RD(SRC); \ } while (0) #ifdef CONFIG_SMP -#ifdef CONFIG_SPARC64 -#define emit_load_cpu(REG) \ - emit_load16(G6, struct thread_info, cpu, REG) -#else #define emit_load_cpu(REG) \ emit_load32(G6, struct thread_info, cpu, REG) -#endif #else #define emit_load_cpu(REG) emit_clear(REG) #endif @@ -486,7 +450,6 @@ void bpf_jit_compile(struct bpf_prog *fp) if (K == 1) break; emit_write_y(G0); -#ifdef CONFIG_SPARC32 /* The Sparc v8 architecture requires * three instructions between a %y * register write and the first use. @@ -494,31 +457,21 @@ void bpf_jit_compile(struct bpf_prog *fp) emit_nop(); emit_nop(); emit_nop(); -#endif emit_alu_K(DIV, K); break; case BPF_ALU | BPF_DIV | BPF_X: /* A /= X; */ emit_cmpi(r_X, 0); if (pc_ret0 > 0) { t_offset = addrs[pc_ret0 - 1]; -#ifdef CONFIG_SPARC32 emit_branch(BE, t_offset + 20); -#else - emit_branch(BE, t_offset + 8); -#endif emit_nop(); /* delay slot */ } else { emit_branch_off(BNE, 16); emit_nop(); -#ifdef CONFIG_SPARC32 emit_jump(cleanup_addr + 20); -#else - emit_jump(cleanup_addr + 8); -#endif emit_clear(r_A); } emit_write_y(G0); -#ifdef CONFIG_SPARC32 /* The Sparc v8 architecture requires * three instructions between a %y * register write and the first use. @@ -526,7 +479,6 @@ void bpf_jit_compile(struct bpf_prog *fp) emit_nop(); emit_nop(); emit_nop(); -#endif emit_alu_X(DIV); break; case BPF_ALU | BPF_NEG: @@ -797,7 +749,6 @@ cond_branch: f_offset = addrs[i + filter[i].jf]; bpf_jit_dump(flen, proglen, pass + 1, image); if (image) { - bpf_flush_icache(image, image + proglen); fp->bpf_func = (void *)image; fp->jited = 1; } diff --git a/arch/sparc/net/bpf_jit_comp_64.c b/arch/sparc/net/bpf_jit_comp_64.c new file mode 100644 index 000000000000..21de77419f48 --- /dev/null +++ b/arch/sparc/net/bpf_jit_comp_64.c @@ -0,0 +1,1566 @@ +#include <linux/moduleloader.h> +#include <linux/workqueue.h> +#include <linux/netdevice.h> +#include <linux/filter.h> +#include <linux/bpf.h> +#include <linux/cache.h> +#include <linux/if_vlan.h> + +#include <asm/cacheflush.h> +#include <asm/ptrace.h> + +#include "bpf_jit_64.h" + +int bpf_jit_enable __read_mostly; + +static inline bool is_simm13(unsigned int value) +{ + return value + 0x1000 < 0x2000; +} + +static inline bool is_simm10(unsigned int value) +{ + return value + 0x200 < 0x400; +} + +static inline bool is_simm5(unsigned int value) +{ + return value + 0x10 < 0x20; +} + +static inline bool is_sethi(unsigned int value) +{ + return (value & ~0x3fffff) == 0; +} + +static void bpf_flush_icache(void *start_, void *end_) +{ + /* Cheetah's I-cache is fully coherent. */ + if (tlb_type == spitfire) { + unsigned long start = (unsigned long) start_; + unsigned long end = (unsigned long) end_; + + start &= ~7UL; + end = (end + 7UL) & ~7UL; + while (start < end) { + flushi(start); + start += 32; + } + } +} + +#define SEEN_DATAREF 1 /* might call external helpers */ +#define SEEN_XREG 2 /* ebx is used */ +#define SEEN_MEM 4 /* use mem[] for temporary storage */ + +#define S13(X) ((X) & 0x1fff) +#define S5(X) ((X) & 0x1f) +#define IMMED 0x00002000 +#define RD(X) ((X) << 25) +#define RS1(X) ((X) << 14) +#define RS2(X) ((X)) +#define OP(X) ((X) << 30) +#define OP2(X) ((X) << 22) +#define OP3(X) ((X) << 19) +#define COND(X) (((X) & 0xf) << 25) +#define CBCOND(X) (((X) & 0x1f) << 25) +#define F1(X) OP(X) +#define F2(X, Y) (OP(X) | OP2(Y)) +#define F3(X, Y) (OP(X) | OP3(Y)) +#define ASI(X) (((X) & 0xff) << 5) + +#define CONDN COND(0x0) +#define CONDE COND(0x1) +#define CONDLE COND(0x2) +#define CONDL COND(0x3) +#define CONDLEU COND(0x4) +#define CONDCS COND(0x5) +#define CONDNEG COND(0x6) +#define CONDVC COND(0x7) +#define CONDA COND(0x8) +#define CONDNE COND(0x9) +#define CONDG COND(0xa) +#define CONDGE COND(0xb) +#define CONDGU COND(0xc) +#define CONDCC COND(0xd) +#define CONDPOS COND(0xe) +#define CONDVS COND(0xf) + +#define CONDGEU CONDCC +#define CONDLU CONDCS + +#define WDISP22(X) (((X) >> 2) & 0x3fffff) +#define WDISP19(X) (((X) >> 2) & 0x7ffff) + +/* The 10-bit branch displacement for CBCOND is split into two fields */ +static u32 WDISP10(u32 off) +{ + u32 ret = ((off >> 2) & 0xff) << 5; + + ret |= ((off >> (2 + 8)) & 0x03) << 19; + + return ret; +} + +#define CBCONDE CBCOND(0x09) +#define CBCONDLE CBCOND(0x0a) +#define CBCONDL CBCOND(0x0b) +#define CBCONDLEU CBCOND(0x0c) +#define CBCONDCS CBCOND(0x0d) +#define CBCONDN CBCOND(0x0e) +#define CBCONDVS CBCOND(0x0f) +#define CBCONDNE CBCOND(0x19) +#define CBCONDG CBCOND(0x1a) +#define CBCONDGE CBCOND(0x1b) +#define CBCONDGU CBCOND(0x1c) +#define CBCONDCC CBCOND(0x1d) +#define CBCONDPOS CBCOND(0x1e) +#define CBCONDVC CBCOND(0x1f) + +#define CBCONDGEU CBCONDCC +#define CBCONDLU CBCONDCS + +#define ANNUL (1 << 29) +#define XCC (1 << 21) + +#define BRANCH (F2(0, 1) | XCC) +#define CBCOND_OP (F2(0, 3) | XCC) + +#define BA (BRANCH | CONDA) +#define BG (BRANCH | CONDG) +#define BGU (BRANCH | CONDGU) +#define BLEU (BRANCH | CONDLEU) +#define BGE (BRANCH | CONDGE) +#define BGEU (BRANCH | CONDGEU) +#define BLU (BRANCH | CONDLU) +#define BE (BRANCH | CONDE) +#define BNE (BRANCH | CONDNE) + +#define SETHI(K, REG) \ + (F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff)) +#define OR_LO(K, REG) \ + (F3(2, 0x02) | IMMED | RS1(REG) | ((K) & 0x3ff) | RD(REG)) + +#define ADD F3(2, 0x00) +#define AND F3(2, 0x01) +#define ANDCC F3(2, 0x11) +#define OR F3(2, 0x02) +#define XOR F3(2, 0x03) +#define SUB F3(2, 0x04) +#define SUBCC F3(2, 0x14) +#define MUL F3(2, 0x0a) +#define MULX F3(2, 0x09) +#define UDIVX F3(2, 0x0d) +#define DIV F3(2, 0x0e) +#define SLL F3(2, 0x25) +#define SLLX (F3(2, 0x25)|(1<<12)) +#define SRA F3(2, 0x27) +#define SRAX (F3(2, 0x27)|(1<<12)) +#define SRL F3(2, 0x26) +#define SRLX (F3(2, 0x26)|(1<<12)) +#define JMPL F3(2, 0x38) +#define SAVE F3(2, 0x3c) +#define RESTORE F3(2, 0x3d) +#define CALL F1(1) +#define BR F2(0, 0x01) +#define RD_Y F3(2, 0x28) +#define WR_Y F3(2, 0x30) + +#define LD32 F3(3, 0x00) +#define LD8 F3(3, 0x01) +#define LD16 F3(3, 0x02) +#define LD64 F3(3, 0x0b) +#define LD64A F3(3, 0x1b) +#define ST8 F3(3, 0x05) +#define ST16 F3(3, 0x06) +#define ST32 F3(3, 0x04) +#define ST64 F3(3, 0x0e) + +#define CAS F3(3, 0x3c) +#define CASX F3(3, 0x3e) + +#define LDPTR LD64 +#define BASE_STACKFRAME 176 + +#define LD32I (LD32 | IMMED) +#define LD8I (LD8 | IMMED) +#define LD16I (LD16 | IMMED) +#define LD64I (LD64 | IMMED) +#define LDPTRI (LDPTR | IMMED) +#define ST32I (ST32 | IMMED) + +struct jit_ctx { + struct bpf_prog *prog; + unsigned int *offset; + int idx; + int epilogue_offset; + bool tmp_1_used; + bool tmp_2_used; + bool tmp_3_used; + bool saw_ld_abs_ind; + bool saw_frame_pointer; + bool saw_call; + bool saw_tail_call; + u32 *image; +}; + +#define TMP_REG_1 (MAX_BPF_JIT_REG + 0) +#define TMP_REG_2 (MAX_BPF_JIT_REG + 1) +#define SKB_HLEN_REG (MAX_BPF_JIT_REG + 2) +#define SKB_DATA_REG (MAX_BPF_JIT_REG + 3) +#define TMP_REG_3 (MAX_BPF_JIT_REG + 4) + +/* Map BPF registers to SPARC registers */ +static const int bpf2sparc[] = { + /* return value from in-kernel function, and exit value from eBPF */ + [BPF_REG_0] = O5, + + /* arguments from eBPF program to in-kernel function */ + [BPF_REG_1] = O0, + [BPF_REG_2] = O1, + [BPF_REG_3] = O2, + [BPF_REG_4] = O3, + [BPF_REG_5] = O4, + + /* callee saved registers that in-kernel function will preserve */ + [BPF_REG_6] = L0, + [BPF_REG_7] = L1, + [BPF_REG_8] = L2, + [BPF_REG_9] = L3, + + /* read-only frame pointer to access stack */ + [BPF_REG_FP] = L6, + + [BPF_REG_AX] = G7, + + /* temporary register for internal BPF JIT */ + [TMP_REG_1] = G1, + [TMP_REG_2] = G2, + [TMP_REG_3] = G3, + + [SKB_HLEN_REG] = L4, + [SKB_DATA_REG] = L5, +}; + +static void emit(const u32 insn, struct jit_ctx *ctx) +{ + if (ctx->image != NULL) + ctx->image[ctx->idx] = insn; + + ctx->idx++; +} + +static void emit_call(u32 *func, struct jit_ctx *ctx) +{ + if (ctx->image != NULL) { + void *here = &ctx->image[ctx->idx]; + unsigned int off; + + off = (void *)func - here; + ctx->image[ctx->idx] = CALL | ((off >> 2) & 0x3fffffff); + } + ctx->idx++; +} + +static void emit_nop(struct jit_ctx *ctx) +{ + emit(SETHI(0, G0), ctx); +} + +static void emit_reg_move(u32 from, u32 to, struct jit_ctx *ctx) +{ + emit(OR | RS1(G0) | RS2(from) | RD(to), ctx); +} + +/* Emit 32-bit constant, zero extended. */ +static void emit_set_const(s32 K, u32 reg, struct jit_ctx *ctx) +{ + emit(SETHI(K, reg), ctx); + emit(OR_LO(K, reg), ctx); +} + +/* Emit 32-bit constant, sign extended. */ +static void emit_set_const_sext(s32 K, u32 reg, struct jit_ctx *ctx) +{ + if (K >= 0) { + emit(SETHI(K, reg), ctx); + emit(OR_LO(K, reg), ctx); + } else { + u32 hbits = ~(u32) K; + u32 lbits = -0x400 | (u32) K; + + emit(SETHI(hbits, reg), ctx); + emit(XOR | IMMED | RS1(reg) | S13(lbits) | RD(reg), ctx); + } +} + +static void emit_alu(u32 opcode, u32 src, u32 dst, struct jit_ctx *ctx) +{ + emit(opcode | RS1(dst) | RS2(src) | RD(dst), ctx); +} + +static void emit_alu3(u32 opcode, u32 a, u32 b, u32 c, struct jit_ctx *ctx) +{ + emit(opcode | RS1(a) | RS2(b) | RD(c), ctx); +} + +static void emit_alu_K(unsigned int opcode, unsigned int dst, unsigned int imm, + struct jit_ctx *ctx) +{ + bool small_immed = is_simm13(imm); + unsigned int insn = opcode; + + insn |= RS1(dst) | RD(dst); + if (small_immed) { + emit(insn | IMMED | S13(imm), ctx); + } else { + unsigned int tmp = bpf2sparc[TMP_REG_1]; + + ctx->tmp_1_used = true; + + emit_set_const_sext(imm, tmp, ctx); + emit(insn | RS2(tmp), ctx); + } +} + +static void emit_alu3_K(unsigned int opcode, unsigned int src, unsigned int imm, + unsigned int dst, struct jit_ctx *ctx) +{ + bool small_immed = is_simm13(imm); + unsigned int insn = opcode; + + insn |= RS1(src) | RD(dst); + if (small_immed) { + emit(insn | IMMED | S13(imm), ctx); + } else { + unsigned int tmp = bpf2sparc[TMP_REG_1]; + + ctx->tmp_1_used = true; + + emit_set_const_sext(imm, tmp, ctx); + emit(insn | RS2(tmp), ctx); + } +} + +static void emit_loadimm32(s32 K, unsigned int dest, struct jit_ctx *ctx) +{ + if (K >= 0 && is_simm13(K)) { + /* or %g0, K, DEST */ + emit(OR | IMMED | RS1(G0) | S13(K) | RD(dest), ctx); + } else { + emit_set_const(K, dest, ctx); + } +} + +static void emit_loadimm(s32 K, unsigned int dest, struct jit_ctx *ctx) +{ + if (is_simm13(K)) { + /* or %g0, K, DEST */ + emit(OR | IMMED | RS1(G0) | S13(K) | RD(dest), ctx); + } else { + emit_set_const(K, dest, ctx); + } +} + +static void emit_loadimm_sext(s32 K, unsigned int dest, struct jit_ctx *ctx) +{ + if (is_simm13(K)) { + /* or %g0, K, DEST */ + emit(OR | IMMED | RS1(G0) | S13(K) | RD(dest), ctx); + } else { + emit_set_const_sext(K, dest, ctx); + } +} + +static void analyze_64bit_constant(u32 high_bits, u32 low_bits, + int *hbsp, int *lbsp, int *abbasp) +{ + int lowest_bit_set, highest_bit_set, all_bits_between_are_set; + int i; + + lowest_bit_set = highest_bit_set = -1; + i = 0; + do { + if ((lowest_bit_set == -1) && ((low_bits >> i) & 1)) + lowest_bit_set = i; + if ((highest_bit_set == -1) && ((high_bits >> (32 - i - 1)) & 1)) + highest_bit_set = (64 - i - 1); + } while (++i < 32 && (highest_bit_set == -1 || + lowest_bit_set == -1)); + if (i == 32) { + i = 0; + do { + if (lowest_bit_set == -1 && ((high_bits >> i) & 1)) + lowest_bit_set = i + 32; + if (highest_bit_set == -1 && + ((low_bits >> (32 - i - 1)) & 1)) + highest_bit_set = 32 - i - 1; + } while (++i < 32 && (highest_bit_set == -1 || + lowest_bit_set == -1)); + } + + all_bits_between_are_set = 1; + for (i = lowest_bit_set; i <= highest_bit_set; i++) { + if (i < 32) { + if ((low_bits & (1 << i)) != 0) + continue; + } else { + if ((high_bits & (1 << (i - 32))) != 0) + continue; + } + all_bits_between_are_set = 0; + break; + } + *hbsp = highest_bit_set; + *lbsp = lowest_bit_set; + *abbasp = all_bits_between_are_set; +} + +static unsigned long create_simple_focus_bits(unsigned long high_bits, + unsigned long low_bits, + int lowest_bit_set, int shift) +{ + long hi, lo; + + if (lowest_bit_set < 32) { + lo = (low_bits >> lowest_bit_set) << shift; + hi = ((high_bits << (32 - lowest_bit_set)) << shift); + } else { + lo = 0; + hi = ((high_bits >> (lowest_bit_set - 32)) << shift); + } + return hi | lo; +} + +static bool const64_is_2insns(unsigned long high_bits, + unsigned long low_bits) +{ + int highest_bit_set, lowest_bit_set, all_bits_between_are_set; + + if (high_bits == 0 || high_bits == 0xffffffff) + return true; + + analyze_64bit_constant(high_bits, low_bits, + &highest_bit_set, &lowest_bit_set, + &all_bits_between_are_set); + + if ((highest_bit_set == 63 || lowest_bit_set == 0) && + all_bits_between_are_set != 0) + return true; + + if (highest_bit_set - lowest_bit_set < 21) + return true; + + return false; +} + +static void sparc_emit_set_const64_quick2(unsigned long high_bits, + unsigned long low_imm, + unsigned int dest, + int shift_count, struct jit_ctx *ctx) +{ + emit_loadimm32(high_bits, dest, ctx); + + /* Now shift it up into place. */ + emit_alu_K(SLLX, dest, shift_count, ctx); + + /* If there is a low immediate part piece, finish up by + * putting that in as well. + */ + if (low_imm != 0) + emit(OR | IMMED | RS1(dest) | S13(low_imm) | RD(dest), ctx); +} + +static void emit_loadimm64(u64 K, unsigned int dest, struct jit_ctx *ctx) +{ + int all_bits_between_are_set, lowest_bit_set, highest_bit_set; + unsigned int tmp = bpf2sparc[TMP_REG_1]; + u32 low_bits = (K & 0xffffffff); + u32 high_bits = (K >> 32); + + /* These two tests also take care of all of the one + * instruction cases. + */ + if (high_bits == 0xffffffff && (low_bits & 0x80000000)) + return emit_loadimm_sext(K, dest, ctx); + if (high_bits == 0x00000000) + return emit_loadimm32(K, dest, ctx); + + analyze_64bit_constant(high_bits, low_bits, &highest_bit_set, + &lowest_bit_set, &all_bits_between_are_set); + + /* 1) mov -1, %reg + * sllx %reg, shift, %reg + * 2) mov -1, %reg + * srlx %reg, shift, %reg + * 3) mov some_small_const, %reg + * sllx %reg, shift, %reg + */ + if (((highest_bit_set == 63 || lowest_bit_set == 0) && + all_bits_between_are_set != 0) || + ((highest_bit_set - lowest_bit_set) < 12)) { + int shift = lowest_bit_set; + long the_const = -1; + + if ((highest_bit_set != 63 && lowest_bit_set != 0) || + all_bits_between_are_set == 0) { + the_const = + create_simple_focus_bits(high_bits, low_bits, + lowest_bit_set, 0); + } else if (lowest_bit_set == 0) + shift = -(63 - highest_bit_set); + + emit(OR | IMMED | RS1(G0) | S13(the_const) | RD(dest), ctx); + if (shift > 0) + emit_alu_K(SLLX, dest, shift, ctx); + else if (shift < 0) + emit_alu_K(SRLX, dest, -shift, ctx); + + return; + } + + /* Now a range of 22 or less bits set somewhere. + * 1) sethi %hi(focus_bits), %reg + * sllx %reg, shift, %reg + * 2) sethi %hi(focus_bits), %reg + * srlx %reg, shift, %reg + */ + if ((highest_bit_set - lowest_bit_set) < 21) { + unsigned long focus_bits = + create_simple_focus_bits(high_bits, low_bits, + lowest_bit_set, 10); + + emit(SETHI(focus_bits, dest), ctx); + + /* If lowest_bit_set == 10 then a sethi alone could + * have done it. + */ + if (lowest_bit_set < 10) + emit_alu_K(SRLX, dest, 10 - lowest_bit_set, ctx); + else if (lowest_bit_set > 10) + emit_alu_K(SLLX, dest, lowest_bit_set - 10, ctx); + return; + } + + /* Ok, now 3 instruction sequences. */ + if (low_bits == 0) { + emit_loadimm32(high_bits, dest, ctx); + emit_alu_K(SLLX, dest, 32, ctx); + return; + } + + /* We may be able to do something quick + * when the constant is negated, so try that. + */ + if (const64_is_2insns((~high_bits) & 0xffffffff, + (~low_bits) & 0xfffffc00)) { + /* NOTE: The trailing bits get XOR'd so we need the + * non-negated bits, not the negated ones. + */ + unsigned long trailing_bits = low_bits & 0x3ff; + + if ((((~high_bits) & 0xffffffff) == 0 && + ((~low_bits) & 0x80000000) == 0) || + (((~high_bits) & 0xffffffff) == 0xffffffff && + ((~low_bits) & 0x80000000) != 0)) { + unsigned long fast_int = (~low_bits & 0xffffffff); + + if ((is_sethi(fast_int) && + (~high_bits & 0xffffffff) == 0)) { + emit(SETHI(fast_int, dest), ctx); + } else if (is_simm13(fast_int)) { + emit(OR | IMMED | RS1(G0) | S13(fast_int) | RD(dest), ctx); + } else { + emit_loadimm64(fast_int, dest, ctx); + } + } else { + u64 n = ((~low_bits) & 0xfffffc00) | + (((unsigned long)((~high_bits) & 0xffffffff))<<32); + emit_loadimm64(n, dest, ctx); + } + + low_bits = -0x400 | trailing_bits; + + emit(XOR | IMMED | RS1(dest) | S13(low_bits) | RD(dest), ctx); + return; + } + + /* 1) sethi %hi(xxx), %reg + * or %reg, %lo(xxx), %reg + * sllx %reg, yyy, %reg + */ + if ((highest_bit_set - lowest_bit_set) < 32) { + unsigned long focus_bits = + create_simple_focus_bits(high_bits, low_bits, + lowest_bit_set, 0); + + /* So what we know is that the set bits straddle the + * middle of the 64-bit word. + */ + sparc_emit_set_const64_quick2(focus_bits, 0, dest, + lowest_bit_set, ctx); + return; + } + + /* 1) sethi %hi(high_bits), %reg + * or %reg, %lo(high_bits), %reg + * sllx %reg, 32, %reg + * or %reg, low_bits, %reg + */ + if (is_simm13(low_bits) && ((int)low_bits > 0)) { + sparc_emit_set_const64_quick2(high_bits, low_bits, + dest, 32, ctx); + return; + } + + /* Oh well, we tried... Do a full 64-bit decomposition. */ + ctx->tmp_1_used = true; + + emit_loadimm32(high_bits, tmp, ctx); + emit_loadimm32(low_bits, dest, ctx); + emit_alu_K(SLLX, tmp, 32, ctx); + emit(OR | RS1(dest) | RS2(tmp) | RD(dest), ctx); +} + +static void emit_branch(unsigned int br_opc, unsigned int from_idx, unsigned int to_idx, + struct jit_ctx *ctx) +{ + unsigned int off = to_idx - from_idx; + + if (br_opc & XCC) + emit(br_opc | WDISP19(off << 2), ctx); + else + emit(br_opc | WDISP22(off << 2), ctx); +} + +static void emit_cbcond(unsigned int cb_opc, unsigned int from_idx, unsigned int to_idx, + const u8 dst, const u8 src, struct jit_ctx *ctx) +{ + unsigned int off = to_idx - from_idx; + + emit(cb_opc | WDISP10(off << 2) | RS1(dst) | RS2(src), ctx); +} + +static void emit_cbcondi(unsigned int cb_opc, unsigned int from_idx, unsigned int to_idx, + const u8 dst, s32 imm, struct jit_ctx *ctx) +{ + unsigned int off = to_idx - from_idx; + + emit(cb_opc | IMMED | WDISP10(off << 2) | RS1(dst) | S5(imm), ctx); +} + +#define emit_read_y(REG, CTX) emit(RD_Y | RD(REG), CTX) +#define emit_write_y(REG, CTX) emit(WR_Y | IMMED | RS1(REG) | S13(0), CTX) + +#define emit_cmp(R1, R2, CTX) \ + emit(SUBCC | RS1(R1) | RS2(R2) | RD(G0), CTX) + +#define emit_cmpi(R1, IMM, CTX) \ + emit(SUBCC | IMMED | RS1(R1) | S13(IMM) | RD(G0), CTX) + +#define emit_btst(R1, R2, CTX) \ + emit(ANDCC | RS1(R1) | RS2(R2) | RD(G0), CTX) + +#define emit_btsti(R1, IMM, CTX) \ + emit(ANDCC | IMMED | RS1(R1) | S13(IMM) | RD(G0), CTX) + +static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src, + const s32 imm, bool is_imm, int branch_dst, + struct jit_ctx *ctx) +{ + bool use_cbcond = (sparc64_elf_hwcap & AV_SPARC_CBCOND) != 0; + const u8 tmp = bpf2sparc[TMP_REG_1]; + + branch_dst = ctx->offset[branch_dst]; + + if (!is_simm10(branch_dst - ctx->idx) || + BPF_OP(code) == BPF_JSET) + use_cbcond = false; + + if (is_imm) { + bool fits = true; + + if (use_cbcond) { + if (!is_simm5(imm)) + fits = false; + } else if (!is_simm13(imm)) { + fits = false; + } + if (!fits) { + ctx->tmp_1_used = true; + emit_loadimm_sext(imm, tmp, ctx); + src = tmp; + is_imm = false; + } + } + + if (!use_cbcond) { + u32 br_opcode; + + if (BPF_OP(code) == BPF_JSET) { + if (is_imm) + emit_btsti(dst, imm, ctx); + else + emit_btst(dst, src, ctx); + } else { + if (is_imm) + emit_cmpi(dst, imm, ctx); + else + emit_cmp(dst, src, ctx); + } + switch (BPF_OP(code)) { + case BPF_JEQ: + br_opcode = BE; + break; + case BPF_JGT: + br_opcode = BGU; + break; + case BPF_JGE: + br_opcode = BGEU; + break; + case BPF_JSET: + case BPF_JNE: + br_opcode = BNE; + break; + case BPF_JSGT: + br_opcode = BG; + break; + case BPF_JSGE: + br_opcode = BGE; + break; + default: + /* Make sure we dont leak kernel information to the + * user. + */ + return -EFAULT; + } + emit_branch(br_opcode, ctx->idx, branch_dst, ctx); + emit_nop(ctx); + } else { + u32 cbcond_opcode; + + switch (BPF_OP(code)) { + case BPF_JEQ: + cbcond_opcode = CBCONDE; + break; + case BPF_JGT: + cbcond_opcode = CBCONDGU; + break; + case BPF_JGE: + cbcond_opcode = CBCONDGEU; + break; + case BPF_JNE: + cbcond_opcode = CBCONDNE; + break; + case BPF_JSGT: + cbcond_opcode = CBCONDG; + break; + case BPF_JSGE: + cbcond_opcode = CBCONDGE; + break; + default: + /* Make sure we dont leak kernel information to the + * user. + */ + return -EFAULT; + } + cbcond_opcode |= CBCOND_OP; + if (is_imm) + emit_cbcondi(cbcond_opcode, ctx->idx, branch_dst, + dst, imm, ctx); + else + emit_cbcond(cbcond_opcode, ctx->idx, branch_dst, + dst, src, ctx); + } + return 0; +} + +static void load_skb_regs(struct jit_ctx *ctx, u8 r_skb) +{ + const u8 r_headlen = bpf2sparc[SKB_HLEN_REG]; + const u8 r_data = bpf2sparc[SKB_DATA_REG]; + const u8 r_tmp = bpf2sparc[TMP_REG_1]; + unsigned int off; + + off = offsetof(struct sk_buff, len); + emit(LD32I | RS1(r_skb) | S13(off) | RD(r_headlen), ctx); + + off = offsetof(struct sk_buff, data_len); + emit(LD32I | RS1(r_skb) | S13(off) | RD(r_tmp), ctx); + + emit(SUB | RS1(r_headlen) | RS2(r_tmp) | RD(r_headlen), ctx); + + off = offsetof(struct sk_buff, data); + emit(LDPTRI | RS1(r_skb) | S13(off) | RD(r_data), ctx); +} + +/* Just skip the save instruction and the ctx register move. */ +#define BPF_TAILCALL_PROLOGUE_SKIP 16 +#define BPF_TAILCALL_CNT_SP_OFF (STACK_BIAS + 128) + +static void build_prologue(struct jit_ctx *ctx) +{ + s32 stack_needed = BASE_STACKFRAME; + + if (ctx->saw_frame_pointer || ctx->saw_tail_call) + stack_needed += MAX_BPF_STACK; + + if (ctx->saw_tail_call) + stack_needed += 8; + + /* save %sp, -176, %sp */ + emit(SAVE | IMMED | RS1(SP) | S13(-stack_needed) | RD(SP), ctx); + + /* tail_call_cnt = 0 */ + if (ctx->saw_tail_call) { + u32 off = BPF_TAILCALL_CNT_SP_OFF; + + emit(ST32 | IMMED | RS1(SP) | S13(off) | RD(G0), ctx); + } else { + emit_nop(ctx); + } + if (ctx->saw_frame_pointer) { + const u8 vfp = bpf2sparc[BPF_REG_FP]; + + emit(ADD | IMMED | RS1(FP) | S13(STACK_BIAS) | RD(vfp), ctx); + } + + emit_reg_move(I0, O0, ctx); + /* If you add anything here, adjust BPF_TAILCALL_PROLOGUE_SKIP above. */ + + if (ctx->saw_ld_abs_ind) + load_skb_regs(ctx, bpf2sparc[BPF_REG_1]); +} + +static void build_epilogue(struct jit_ctx *ctx) +{ + ctx->epilogue_offset = ctx->idx; + + /* ret (jmpl %i7 + 8, %g0) */ + emit(JMPL | IMMED | RS1(I7) | S13(8) | RD(G0), ctx); + + /* restore %i5, %g0, %o0 */ + emit(RESTORE | RS1(bpf2sparc[BPF_REG_0]) | RS2(G0) | RD(O0), ctx); +} + +static void emit_tail_call(struct jit_ctx *ctx) +{ + const u8 bpf_array = bpf2sparc[BPF_REG_2]; + const u8 bpf_index = bpf2sparc[BPF_REG_3]; + const u8 tmp = bpf2sparc[TMP_REG_1]; + u32 off; + + ctx->saw_tail_call = true; + + off = offsetof(struct bpf_array, map.max_entries); + emit(LD32 | IMMED | RS1(bpf_array) | S13(off) | RD(tmp), ctx); + emit_cmp(bpf_index, tmp, ctx); +#define OFFSET1 17 + emit_branch(BGEU, ctx->idx, ctx->idx + OFFSET1, ctx); + emit_nop(ctx); + + off = BPF_TAILCALL_CNT_SP_OFF; + emit(LD32 | IMMED | RS1(SP) | S13(off) | RD(tmp), ctx); + emit_cmpi(tmp, MAX_TAIL_CALL_CNT, ctx); +#define OFFSET2 13 + emit_branch(BGU, ctx->idx, ctx->idx + OFFSET2, ctx); + emit_nop(ctx); + + emit_alu_K(ADD, tmp, 1, ctx); + off = BPF_TAILCALL_CNT_SP_OFF; + emit(ST32 | IMMED | RS1(SP) | S13(off) | RD(tmp), ctx); + + emit_alu3_K(SLL, bpf_index, 3, tmp, ctx); + emit_alu(ADD, bpf_array, tmp, ctx); + off = offsetof(struct bpf_array, ptrs); + emit(LD64 | IMMED | RS1(tmp) | S13(off) | RD(tmp), ctx); + + emit_cmpi(tmp, 0, ctx); +#define OFFSET3 5 + emit_branch(BE, ctx->idx, ctx->idx + OFFSET3, ctx); + emit_nop(ctx); + + off = offsetof(struct bpf_prog, bpf_func); + emit(LD64 | IMMED | RS1(tmp) | S13(off) | RD(tmp), ctx); + + off = BPF_TAILCALL_PROLOGUE_SKIP; + emit(JMPL | IMMED | RS1(tmp) | S13(off) | RD(G0), ctx); + emit_nop(ctx); +} + +static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) +{ + const u8 code = insn->code; + const u8 dst = bpf2sparc[insn->dst_reg]; + const u8 src = bpf2sparc[insn->src_reg]; + const int i = insn - ctx->prog->insnsi; + const s16 off = insn->off; + const s32 imm = insn->imm; + u32 *func; + + if (insn->src_reg == BPF_REG_FP) + ctx->saw_frame_pointer = true; + + switch (code) { + /* dst = src */ + case BPF_ALU | BPF_MOV | BPF_X: + emit_alu3_K(SRL, src, 0, dst, ctx); + break; + case BPF_ALU64 | BPF_MOV | BPF_X: + emit_reg_move(src, dst, ctx); + break; + /* dst = dst OP src */ + case BPF_ALU | BPF_ADD | BPF_X: + case BPF_ALU64 | BPF_ADD | BPF_X: + emit_alu(ADD, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_SUB | BPF_X: + case BPF_ALU64 | BPF_SUB | BPF_X: + emit_alu(SUB, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_AND | BPF_X: + case BPF_ALU64 | BPF_AND | BPF_X: + emit_alu(AND, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_OR | BPF_X: + case BPF_ALU64 | BPF_OR | BPF_X: + emit_alu(OR, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_XOR | BPF_X: + case BPF_ALU64 | BPF_XOR | BPF_X: + emit_alu(XOR, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_MUL | BPF_X: + emit_alu(MUL, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_MUL | BPF_X: + emit_alu(MULX, src, dst, ctx); + break; + case BPF_ALU | BPF_DIV | BPF_X: + emit_cmp(src, G0, ctx); + emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); + emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); + + emit_write_y(G0, ctx); + emit_alu(DIV, src, dst, ctx); + break; + + case BPF_ALU64 | BPF_DIV | BPF_X: + emit_cmp(src, G0, ctx); + emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); + emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); + + emit_alu(UDIVX, src, dst, ctx); + break; + + case BPF_ALU | BPF_MOD | BPF_X: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + + ctx->tmp_1_used = true; + + emit_cmp(src, G0, ctx); + emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); + emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); + + emit_write_y(G0, ctx); + emit_alu3(DIV, dst, src, tmp, ctx); + emit_alu3(MULX, tmp, src, tmp, ctx); + emit_alu3(SUB, dst, tmp, dst, ctx); + goto do_alu32_trunc; + } + case BPF_ALU64 | BPF_MOD | BPF_X: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + + ctx->tmp_1_used = true; + + emit_cmp(src, G0, ctx); + emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); + emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); + + emit_alu3(UDIVX, dst, src, tmp, ctx); + emit_alu3(MULX, tmp, src, tmp, ctx); + emit_alu3(SUB, dst, tmp, dst, ctx); + break; + } + case BPF_ALU | BPF_LSH | BPF_X: + emit_alu(SLL, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_LSH | BPF_X: + emit_alu(SLLX, src, dst, ctx); + break; + case BPF_ALU | BPF_RSH | BPF_X: + emit_alu(SRL, src, dst, ctx); + break; + case BPF_ALU64 | BPF_RSH | BPF_X: + emit_alu(SRLX, src, dst, ctx); + break; + case BPF_ALU | BPF_ARSH | BPF_X: + emit_alu(SRA, src, dst, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_ARSH | BPF_X: + emit_alu(SRAX, src, dst, ctx); + break; + + /* dst = -dst */ + case BPF_ALU | BPF_NEG: + case BPF_ALU64 | BPF_NEG: + emit(SUB | RS1(0) | RS2(dst) | RD(dst), ctx); + goto do_alu32_trunc; + + case BPF_ALU | BPF_END | BPF_FROM_BE: + switch (imm) { + case 16: + emit_alu_K(SLL, dst, 16, ctx); + emit_alu_K(SRL, dst, 16, ctx); + break; + case 32: + emit_alu_K(SRL, dst, 0, ctx); + break; + case 64: + /* nop */ + break; + + } + break; + + /* dst = BSWAP##imm(dst) */ + case BPF_ALU | BPF_END | BPF_FROM_LE: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + const u8 tmp2 = bpf2sparc[TMP_REG_2]; + + ctx->tmp_1_used = true; + switch (imm) { + case 16: + emit_alu3_K(AND, dst, 0xff, tmp, ctx); + emit_alu3_K(SRL, dst, 8, dst, ctx); + emit_alu3_K(AND, dst, 0xff, dst, ctx); + emit_alu3_K(SLL, tmp, 8, tmp, ctx); + emit_alu(OR, tmp, dst, ctx); + break; + + case 32: + ctx->tmp_2_used = true; + emit_alu3_K(SRL, dst, 24, tmp, ctx); /* tmp = dst >> 24 */ + emit_alu3_K(SRL, dst, 16, tmp2, ctx); /* tmp2 = dst >> 16 */ + emit_alu3_K(AND, tmp2, 0xff, tmp2, ctx);/* tmp2 = tmp2 & 0xff */ + emit_alu3_K(SLL, tmp2, 8, tmp2, ctx); /* tmp2 = tmp2 << 8 */ + emit_alu(OR, tmp2, tmp, ctx); /* tmp = tmp | tmp2 */ + emit_alu3_K(SRL, dst, 8, tmp2, ctx); /* tmp2 = dst >> 8 */ + emit_alu3_K(AND, tmp2, 0xff, tmp2, ctx);/* tmp2 = tmp2 & 0xff */ + emit_alu3_K(SLL, tmp2, 16, tmp2, ctx); /* tmp2 = tmp2 << 16 */ + emit_alu(OR, tmp2, tmp, ctx); /* tmp = tmp | tmp2 */ + emit_alu3_K(AND, dst, 0xff, dst, ctx); /* dst = dst & 0xff */ + emit_alu3_K(SLL, dst, 24, dst, ctx); /* dst = dst << 24 */ + emit_alu(OR, tmp, dst, ctx); /* dst = dst | tmp */ + break; + + case 64: + emit_alu3_K(ADD, SP, STACK_BIAS + 128, tmp, ctx); + emit(ST64 | RS1(tmp) | RS2(G0) | RD(dst), ctx); + emit(LD64A | ASI(ASI_PL) | RS1(tmp) | RS2(G0) | RD(dst), ctx); + break; + } + break; + } + /* dst = imm */ + case BPF_ALU | BPF_MOV | BPF_K: + emit_loadimm32(imm, dst, ctx); + break; + case BPF_ALU64 | BPF_MOV | BPF_K: + emit_loadimm_sext(imm, dst, ctx); + break; + /* dst = dst OP imm */ + case BPF_ALU | BPF_ADD | BPF_K: + case BPF_ALU64 | BPF_ADD | BPF_K: + emit_alu_K(ADD, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_SUB | BPF_K: + case BPF_ALU64 | BPF_SUB | BPF_K: + emit_alu_K(SUB, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_AND | BPF_K: + case BPF_ALU64 | BPF_AND | BPF_K: + emit_alu_K(AND, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_OR | BPF_K: + case BPF_ALU64 | BPF_OR | BPF_K: + emit_alu_K(OR, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_XOR | BPF_K: + case BPF_ALU64 | BPF_XOR | BPF_K: + emit_alu_K(XOR, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU | BPF_MUL | BPF_K: + emit_alu_K(MUL, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_MUL | BPF_K: + emit_alu_K(MULX, dst, imm, ctx); + break; + case BPF_ALU | BPF_DIV | BPF_K: + if (imm == 0) + return -EINVAL; + + emit_write_y(G0, ctx); + emit_alu_K(DIV, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_DIV | BPF_K: + if (imm == 0) + return -EINVAL; + + emit_alu_K(UDIVX, dst, imm, ctx); + break; + case BPF_ALU64 | BPF_MOD | BPF_K: + case BPF_ALU | BPF_MOD | BPF_K: { + const u8 tmp = bpf2sparc[TMP_REG_2]; + unsigned int div; + + if (imm == 0) + return -EINVAL; + + div = (BPF_CLASS(code) == BPF_ALU64) ? UDIVX : DIV; + + ctx->tmp_2_used = true; + + if (BPF_CLASS(code) != BPF_ALU64) + emit_write_y(G0, ctx); + if (is_simm13(imm)) { + emit(div | IMMED | RS1(dst) | S13(imm) | RD(tmp), ctx); + emit(MULX | IMMED | RS1(tmp) | S13(imm) | RD(tmp), ctx); + emit(SUB | RS1(dst) | RS2(tmp) | RD(dst), ctx); + } else { + const u8 tmp1 = bpf2sparc[TMP_REG_1]; + + ctx->tmp_1_used = true; + + emit_set_const_sext(imm, tmp1, ctx); + emit(div | RS1(dst) | RS2(tmp1) | RD(tmp), ctx); + emit(MULX | RS1(tmp) | RS2(tmp1) | RD(tmp), ctx); + emit(SUB | RS1(dst) | RS2(tmp) | RD(dst), ctx); + } + goto do_alu32_trunc; + } + case BPF_ALU | BPF_LSH | BPF_K: + emit_alu_K(SLL, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_LSH | BPF_K: + emit_alu_K(SLLX, dst, imm, ctx); + break; + case BPF_ALU | BPF_RSH | BPF_K: + emit_alu_K(SRL, dst, imm, ctx); + break; + case BPF_ALU64 | BPF_RSH | BPF_K: + emit_alu_K(SRLX, dst, imm, ctx); + break; + case BPF_ALU | BPF_ARSH | BPF_K: + emit_alu_K(SRA, dst, imm, ctx); + goto do_alu32_trunc; + case BPF_ALU64 | BPF_ARSH | BPF_K: + emit_alu_K(SRAX, dst, imm, ctx); + break; + + do_alu32_trunc: + if (BPF_CLASS(code) == BPF_ALU) + emit_alu_K(SRL, dst, 0, ctx); + break; + + /* JUMP off */ + case BPF_JMP | BPF_JA: + emit_branch(BA, ctx->idx, ctx->offset[i + off], ctx); + emit_nop(ctx); + break; + /* IF (dst COND src) JUMP off */ + case BPF_JMP | BPF_JEQ | BPF_X: + case BPF_JMP | BPF_JGT | BPF_X: + case BPF_JMP | BPF_JGE | BPF_X: + case BPF_JMP | BPF_JNE | BPF_X: + case BPF_JMP | BPF_JSGT | BPF_X: + case BPF_JMP | BPF_JSGE | BPF_X: + case BPF_JMP | BPF_JSET | BPF_X: { + int err; + + err = emit_compare_and_branch(code, dst, src, 0, false, i + off, ctx); + if (err) + return err; + break; + } + /* IF (dst COND imm) JUMP off */ + case BPF_JMP | BPF_JEQ | BPF_K: + case BPF_JMP | BPF_JGT | BPF_K: + case BPF_JMP | BPF_JGE | BPF_K: + case BPF_JMP | BPF_JNE | BPF_K: + case BPF_JMP | BPF_JSGT | BPF_K: + case BPF_JMP | BPF_JSGE | BPF_K: + case BPF_JMP | BPF_JSET | BPF_K: { + int err; + + err = emit_compare_and_branch(code, dst, 0, imm, true, i + off, ctx); + if (err) + return err; + break; + } + + /* function call */ + case BPF_JMP | BPF_CALL: + { + u8 *func = ((u8 *)__bpf_call_base) + imm; + + ctx->saw_call = true; + + emit_call((u32 *)func, ctx); + emit_nop(ctx); + + emit_reg_move(O0, bpf2sparc[BPF_REG_0], ctx); + + if (bpf_helper_changes_pkt_data(func) && ctx->saw_ld_abs_ind) + load_skb_regs(ctx, bpf2sparc[BPF_REG_6]); + break; + } + + /* tail call */ + case BPF_JMP | BPF_CALL |BPF_X: + emit_tail_call(ctx); + break; + + /* function return */ + case BPF_JMP | BPF_EXIT: + /* Optimization: when last instruction is EXIT, + simply fallthrough to epilogue. */ + if (i == ctx->prog->len - 1) + break; + emit_branch(BA, ctx->idx, ctx->epilogue_offset, ctx); + emit_nop(ctx); + break; + + /* dst = imm64 */ + case BPF_LD | BPF_IMM | BPF_DW: + { + const struct bpf_insn insn1 = insn[1]; + u64 imm64; + + imm64 = (u64)insn1.imm << 32 | (u32)imm; + emit_loadimm64(imm64, dst, ctx); + + return 1; + } + + /* LDX: dst = *(size *)(src + off) */ + case BPF_LDX | BPF_MEM | BPF_W: + case BPF_LDX | BPF_MEM | BPF_H: + case BPF_LDX | BPF_MEM | BPF_B: + case BPF_LDX | BPF_MEM | BPF_DW: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + u32 opcode = 0, rs2; + + ctx->tmp_1_used = true; + switch (BPF_SIZE(code)) { + case BPF_W: + opcode = LD32; + break; + case BPF_H: + opcode = LD16; + break; + case BPF_B: + opcode = LD8; + break; + case BPF_DW: + opcode = LD64; + break; + } + + if (is_simm13(off)) { + opcode |= IMMED; + rs2 = S13(off); + } else { + emit_loadimm(off, tmp, ctx); + rs2 = RS2(tmp); + } + emit(opcode | RS1(src) | rs2 | RD(dst), ctx); + break; + } + /* ST: *(size *)(dst + off) = imm */ + case BPF_ST | BPF_MEM | BPF_W: + case BPF_ST | BPF_MEM | BPF_H: + case BPF_ST | BPF_MEM | BPF_B: + case BPF_ST | BPF_MEM | BPF_DW: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + const u8 tmp2 = bpf2sparc[TMP_REG_2]; + u32 opcode = 0, rs2; + + ctx->tmp_2_used = true; + emit_loadimm(imm, tmp2, ctx); + + switch (BPF_SIZE(code)) { + case BPF_W: + opcode = ST32; + break; + case BPF_H: + opcode = ST16; + break; + case BPF_B: + opcode = ST8; + break; + case BPF_DW: + opcode = ST64; + break; + } + + if (is_simm13(off)) { + opcode |= IMMED; + rs2 = S13(off); + } else { + ctx->tmp_1_used = true; + emit_loadimm(off, tmp, ctx); + rs2 = RS2(tmp); + } + emit(opcode | RS1(dst) | rs2 | RD(tmp2), ctx); + break; + } + + /* STX: *(size *)(dst + off) = src */ + case BPF_STX | BPF_MEM | BPF_W: + case BPF_STX | BPF_MEM | BPF_H: + case BPF_STX | BPF_MEM | BPF_B: + case BPF_STX | BPF_MEM | BPF_DW: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + u32 opcode = 0, rs2; + + switch (BPF_SIZE(code)) { + case BPF_W: + opcode = ST32; + break; + case BPF_H: + opcode = ST16; + break; + case BPF_B: + opcode = ST8; + break; + case BPF_DW: + opcode = ST64; + break; + } + if (is_simm13(off)) { + opcode |= IMMED; + rs2 = S13(off); + } else { + ctx->tmp_1_used = true; + emit_loadimm(off, tmp, ctx); + rs2 = RS2(tmp); + } + emit(opcode | RS1(dst) | rs2 | RD(src), ctx); + break; + } + + /* STX XADD: lock *(u32 *)(dst + off) += src */ + case BPF_STX | BPF_XADD | BPF_W: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + const u8 tmp2 = bpf2sparc[TMP_REG_2]; + const u8 tmp3 = bpf2sparc[TMP_REG_3]; + + ctx->tmp_1_used = true; + ctx->tmp_2_used = true; + ctx->tmp_3_used = true; + emit_loadimm(off, tmp, ctx); + emit_alu3(ADD, dst, tmp, tmp, ctx); + + emit(LD32 | RS1(tmp) | RS2(G0) | RD(tmp2), ctx); + emit_alu3(ADD, tmp2, src, tmp3, ctx); + emit(CAS | ASI(ASI_P) | RS1(tmp) | RS2(tmp2) | RD(tmp3), ctx); + emit_cmp(tmp2, tmp3, ctx); + emit_branch(BNE, 4, 0, ctx); + emit_nop(ctx); + break; + } + /* STX XADD: lock *(u64 *)(dst + off) += src */ + case BPF_STX | BPF_XADD | BPF_DW: { + const u8 tmp = bpf2sparc[TMP_REG_1]; + const u8 tmp2 = bpf2sparc[TMP_REG_2]; + const u8 tmp3 = bpf2sparc[TMP_REG_3]; + + ctx->tmp_1_used = true; + ctx->tmp_2_used = true; + ctx->tmp_3_used = true; + emit_loadimm(off, tmp, ctx); + emit_alu3(ADD, dst, tmp, tmp, ctx); + + emit(LD64 | RS1(tmp) | RS2(G0) | RD(tmp2), ctx); + emit_alu3(ADD, tmp2, src, tmp3, ctx); + emit(CASX | ASI(ASI_P) | RS1(tmp) | RS2(tmp2) | RD(tmp3), ctx); + emit_cmp(tmp2, tmp3, ctx); + emit_branch(BNE, 4, 0, ctx); + emit_nop(ctx); + break; + } +#define CHOOSE_LOAD_FUNC(K, func) \ + ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) + + /* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */ + case BPF_LD | BPF_ABS | BPF_W: + func = CHOOSE_LOAD_FUNC(imm, bpf_jit_load_word); + goto common_load; + case BPF_LD | BPF_ABS | BPF_H: + func = CHOOSE_LOAD_FUNC(imm, bpf_jit_load_half); + goto common_load; + case BPF_LD | BPF_ABS | BPF_B: + func = CHOOSE_LOAD_FUNC(imm, bpf_jit_load_byte); + goto common_load; + /* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + src + imm)) */ + case BPF_LD | BPF_IND | BPF_W: + func = bpf_jit_load_word; + goto common_load; + case BPF_LD | BPF_IND | BPF_H: + func = bpf_jit_load_half; + goto common_load; + + case BPF_LD | BPF_IND | BPF_B: + func = bpf_jit_load_byte; + common_load: + ctx->saw_ld_abs_ind = true; + + emit_reg_move(bpf2sparc[BPF_REG_6], O0, ctx); + emit_loadimm(imm, O1, ctx); + + if (BPF_MODE(code) == BPF_IND) + emit_alu(ADD, src, O1, ctx); + + emit_call(func, ctx); + emit_alu_K(SRA, O1, 0, ctx); + + emit_reg_move(O0, bpf2sparc[BPF_REG_0], ctx); + break; + + default: + pr_err_once("unknown opcode %02x\n", code); + return -EINVAL; + } + + return 0; +} + +static int build_body(struct jit_ctx *ctx) +{ + const struct bpf_prog *prog = ctx->prog; + int i; + + for (i = 0; i < prog->len; i++) { + const struct bpf_insn *insn = &prog->insnsi[i]; + int ret; + + ret = build_insn(insn, ctx); + + if (ret > 0) { + i++; + ctx->offset[i] = ctx->idx; + continue; + } + ctx->offset[i] = ctx->idx; + if (ret) + return ret; + } + return 0; +} + +static void jit_fill_hole(void *area, unsigned int size) +{ + u32 *ptr; + /* We are guaranteed to have aligned memory. */ + for (ptr = area; size >= sizeof(u32); size -= sizeof(u32)) + *ptr++ = 0x91d02005; /* ta 5 */ +} + +struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) +{ + struct bpf_prog *tmp, *orig_prog = prog; + struct bpf_binary_header *header; + bool tmp_blinded = false; + struct jit_ctx ctx; + u32 image_size; + u8 *image_ptr; + int pass; + + if (!bpf_jit_enable) + return orig_prog; + + tmp = bpf_jit_blind_constants(prog); + /* If blinding was requested and we failed during blinding, + * we must fall back to the interpreter. + */ + if (IS_ERR(tmp)) + return orig_prog; + if (tmp != prog) { + tmp_blinded = true; + prog = tmp; + } + + memset(&ctx, 0, sizeof(ctx)); + ctx.prog = prog; + + ctx.offset = kcalloc(prog->len, sizeof(unsigned int), GFP_KERNEL); + if (ctx.offset == NULL) { + prog = orig_prog; + goto out; + } + + /* Fake pass to detect features used, and get an accurate assessment + * of what the final image size will be. + */ + if (build_body(&ctx)) { + prog = orig_prog; + goto out_off; + } + build_prologue(&ctx); + build_epilogue(&ctx); + + /* Now we know the actual image size. */ + image_size = sizeof(u32) * ctx.idx; + header = bpf_jit_binary_alloc(image_size, &image_ptr, + sizeof(u32), jit_fill_hole); + if (header == NULL) { + prog = orig_prog; + goto out_off; + } + + ctx.image = (u32 *)image_ptr; + + for (pass = 1; pass < 3; pass++) { + ctx.idx = 0; + + build_prologue(&ctx); + + if (build_body(&ctx)) { + bpf_jit_binary_free(header); + prog = orig_prog; + goto out_off; + } + + build_epilogue(&ctx); + + if (bpf_jit_enable > 1) + pr_info("Pass %d: shrink = %d, seen = [%c%c%c%c%c%c%c]\n", pass, + image_size - (ctx.idx * 4), + ctx.tmp_1_used ? '1' : ' ', + ctx.tmp_2_used ? '2' : ' ', + ctx.tmp_3_used ? '3' : ' ', + ctx.saw_ld_abs_ind ? 'L' : ' ', + ctx.saw_frame_pointer ? 'F' : ' ', + ctx.saw_call ? 'C' : ' ', + ctx.saw_tail_call ? 'T' : ' '); + } + + if (bpf_jit_enable > 1) + bpf_jit_dump(prog->len, image_size, pass, ctx.image); + + bpf_flush_icache(header, (u8 *)header + (header->pages * PAGE_SIZE)); + + bpf_jit_binary_lock_ro(header); + + prog->bpf_func = (void *)ctx.image; + prog->jited = 1; + +out_off: + kfree(ctx.offset); +out: + if (tmp_blinded) + bpf_jit_prog_release_other(prog, prog == orig_prog ? + tmp : orig_prog); + return prog; +} diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig index fd122ef45b00..0d925fa0f0c1 100644 --- a/arch/tile/configs/tilegx_defconfig +++ b/arch/tile/configs/tilegx_defconfig @@ -249,7 +249,6 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_TILE=y CONFIG_EXT2_FS=y diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig index eb6a55944191..149d8e8eacb8 100644 --- a/arch/tile/configs/tilepro_defconfig +++ b/arch/tile/configs/tilepro_defconfig @@ -358,7 +358,6 @@ CONFIG_WATCHDOG_NOWAYOUT=y # CONFIG_VGA_ARB is not set # CONFIG_USB_SUPPORT is not set CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_TILE=y CONFIG_EXT2_FS=y diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index aa48b6eaff2d..24c44e93804d 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -7,6 +7,7 @@ generic-y += clkdev.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += hw_irq.h diff --git a/arch/tile/include/asm/pgtable_32.h b/arch/tile/include/asm/pgtable_32.h index d26a42279036..5f8c615cb5e9 100644 --- a/arch/tile/include/asm/pgtable_32.h +++ b/arch/tile/include/asm/pgtable_32.h @@ -74,6 +74,7 @@ extern unsigned long VMALLOC_RESERVE /* = CONFIG_VMALLOC_RESERVE */; #define MAXMEM (_VMALLOC_START - PAGE_OFFSET) /* We have no pmd or pud since we are strictly a two-level page table */ +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> static inline int pud_huge_page(pud_t pud) { return 0; } diff --git a/arch/tile/include/asm/pgtable_64.h b/arch/tile/include/asm/pgtable_64.h index e96cec52f6d8..96fe58b45118 100644 --- a/arch/tile/include/asm/pgtable_64.h +++ b/arch/tile/include/asm/pgtable_64.h @@ -59,6 +59,7 @@ #ifndef __ASSEMBLY__ /* We have no pud since we are a three-level page table. */ +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> /* diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h index a77369e91e54..a803f6bb4d92 100644 --- a/arch/tile/include/asm/uaccess.h +++ b/arch/tile/include/asm/uaccess.h @@ -18,15 +18,11 @@ /* * User space memory access functions */ -#include <linux/sched.h> #include <linux/mm.h> #include <asm-generic/uaccess-unaligned.h> #include <asm/processor.h> #include <asm/page.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - /* * The fs value determines whether argument validity checking should be * performed or not. If get_fs() == USER_DS, checking is performed, with @@ -102,24 +98,7 @@ int __range_ok(unsigned long addr, unsigned long size); likely(__range_ok((unsigned long)(addr), (size)) == 0); \ }) -/* - * 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; -}; - -extern int fixup_exception(struct pt_regs *regs); +#include <asm/extable.h> /* * This is a type: either unsigned long, if the argument fits into @@ -334,145 +313,16 @@ extern int __put_user_bad(void) ((x) = 0, -EFAULT); \ }) -/** - * __copy_to_user() - copy data into user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * An alternate version - __copy_to_user_inatomic() - is designed - * to be called from atomic context, typically bracketed by calls - * to pagefault_disable() and pagefault_enable(). - */ -extern unsigned long __must_check __copy_to_user_inatomic( - void __user *to, const void *from, unsigned long n); - -static inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) -{ - might_fault(); - return __copy_to_user_inatomic(to, from, n); -} - -static inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); - return n; -} - -/** - * __copy_from_user() - copy data from user space, with less checking. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - * - * An alternate version - __copy_from_user_inatomic() - is designed - * to be called from atomic context, typically bracketed by calls - * to pagefault_disable() and pagefault_enable(). This version - * does *NOT* pad with zeros. - */ -extern unsigned long __must_check __copy_from_user_inatomic( - void *to, const void __user *from, unsigned long n); -extern unsigned long __must_check __copy_from_user_zeroing( - void *to, const void __user *from, unsigned long n); - -static inline unsigned long __must_check -__copy_from_user(void *to, const void __user *from, unsigned long n) -{ - might_fault(); - return __copy_from_user_zeroing(to, from, n); -} - -static inline unsigned long __must_check -_copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); - else - memset(to, 0, n); - return n; -} - -extern void __compiletime_error("usercopy buffer size is too small") -__bad_copy_user(void); - -static inline void copy_user_overflow(int size, unsigned long count) -{ - WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); -} - -static inline unsigned long __must_check copy_from_user(void *to, - const void __user *from, - unsigned long n) -{ - int sz = __compiletime_object_size(to); - - if (likely(sz == -1 || sz >= n)) - n = _copy_from_user(to, from, n); - else if (!__builtin_constant_p(n)) - copy_user_overflow(sz, n); - else - __bad_copy_user(); - - return n; -} +extern unsigned long __must_check +raw_copy_to_user(void __user *to, const void *from, unsigned long n); +extern unsigned long __must_check +raw_copy_from_user(void *to, const void __user *from, unsigned long n); +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER #ifdef __tilegx__ -/** - * __copy_in_user() - copy data within user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to user space. Caller must check - * the specified blocks with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -extern unsigned long __copy_in_user_inatomic( +extern unsigned long raw_copy_in_user( void __user *to, const void __user *from, unsigned long n); - -static inline unsigned long __must_check -__copy_in_user(void __user *to, const void __user *from, unsigned long n) -{ - might_fault(); - return __copy_in_user_inatomic(to, from, n); -} - -static inline unsigned long __must_check -copy_in_user(void __user *to, const void __user *from, unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n)) - n = __copy_in_user(to, from, n); - return n; -} #endif diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 5bd4e88c7c60..6643ffbc0615 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -155,6 +155,8 @@ static DEFINE_PER_CPU(struct clock_event_device, tile_timer) = { .name = "tile timer", .features = CLOCK_EVT_FEAT_ONESHOT, .min_delta_ns = 1000, + .min_delta_ticks = 1, + .max_delta_ticks = MAX_TICK, .rating = 100, .irq = -1, .set_next_event = tile_timer_set_next_event, diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c index c5369fe643c7..ecce8e177e3f 100644 --- a/arch/tile/lib/exports.c +++ b/arch/tile/lib/exports.c @@ -38,11 +38,10 @@ EXPORT_SYMBOL(__mcount); /* arch/tile/lib/, various memcpy files */ EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(__copy_to_user_inatomic); -EXPORT_SYMBOL(__copy_from_user_inatomic); -EXPORT_SYMBOL(__copy_from_user_zeroing); +EXPORT_SYMBOL(raw_copy_to_user); +EXPORT_SYMBOL(raw_copy_from_user); #ifdef __tilegx__ -EXPORT_SYMBOL(__copy_in_user_inatomic); +EXPORT_SYMBOL(raw_copy_in_user); #endif /* hypervisor glue */ diff --git a/arch/tile/lib/memcpy_32.S b/arch/tile/lib/memcpy_32.S index a2771ae5da53..270f1267cd18 100644 --- a/arch/tile/lib/memcpy_32.S +++ b/arch/tile/lib/memcpy_32.S @@ -24,7 +24,6 @@ #define IS_MEMCPY 0 #define IS_COPY_FROM_USER 1 -#define IS_COPY_FROM_USER_ZEROING 2 #define IS_COPY_TO_USER -1 .section .text.memcpy_common, "ax" @@ -42,40 +41,31 @@ 9 -/* __copy_from_user_inatomic takes the kernel target address in r0, +/* raw_copy_from_user takes the kernel target address in r0, * the user source in r1, and the bytes to copy in r2. * It returns the number of uncopiable bytes (hopefully zero) in r0. */ -ENTRY(__copy_from_user_inatomic) -.type __copy_from_user_inatomic, @function - FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \ +ENTRY(raw_copy_from_user) +.type raw_copy_from_user, @function + FEEDBACK_ENTER_EXPLICIT(raw_copy_from_user, \ .text.memcpy_common, \ - .Lend_memcpy_common - __copy_from_user_inatomic) + .Lend_memcpy_common - raw_copy_from_user) { movei r29, IS_COPY_FROM_USER; j memcpy_common } - .size __copy_from_user_inatomic, . - __copy_from_user_inatomic + .size raw_copy_from_user, . - raw_copy_from_user -/* __copy_from_user_zeroing is like __copy_from_user_inatomic, but - * any uncopiable bytes are zeroed in the target. - */ -ENTRY(__copy_from_user_zeroing) -.type __copy_from_user_zeroing, @function - FEEDBACK_REENTER(__copy_from_user_inatomic) - { movei r29, IS_COPY_FROM_USER_ZEROING; j memcpy_common } - .size __copy_from_user_zeroing, . - __copy_from_user_zeroing - -/* __copy_to_user_inatomic takes the user target address in r0, +/* raw_copy_to_user takes the user target address in r0, * the kernel source in r1, and the bytes to copy in r2. * It returns the number of uncopiable bytes (hopefully zero) in r0. */ -ENTRY(__copy_to_user_inatomic) -.type __copy_to_user_inatomic, @function - FEEDBACK_REENTER(__copy_from_user_inatomic) +ENTRY(raw_copy_to_user) +.type raw_copy_to_user, @function + FEEDBACK_REENTER(raw_copy_from_user) { movei r29, IS_COPY_TO_USER; j memcpy_common } - .size __copy_to_user_inatomic, . - __copy_to_user_inatomic + .size raw_copy_to_user, . - raw_copy_to_user ENTRY(memcpy) .type memcpy, @function - FEEDBACK_REENTER(__copy_from_user_inatomic) + FEEDBACK_REENTER(raw_copy_from_user) { movei r29, IS_MEMCPY } .size memcpy, . - memcpy /* Fall through */ @@ -520,12 +510,7 @@ copy_from_user_fixup_loop: { bnzt r2, copy_from_user_fixup_loop } .Lcopy_from_user_fixup_zero_remainder: - { bbs r29, 2f } /* low bit set means IS_COPY_FROM_USER */ - /* byte-at-a-time loop faulted, so zero the rest. */ - { move r3, r2; bz r2, 2f /* should be impossible, but handle it. */ } -1: { sb r0, zero; addi r0, r0, 1; addi r3, r3, -1 } - { bnzt r3, 1b } -2: move lr, r27 + move lr, r27 { move r0, r2; jrp lr } copy_to_user_fixup_loop: diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c index 97bbb6060b25..a3fea9fd973e 100644 --- a/arch/tile/lib/memcpy_user_64.c +++ b/arch/tile/lib/memcpy_user_64.c @@ -51,7 +51,7 @@ __v; \ }) -#define USERCOPY_FUNC __copy_to_user_inatomic +#define USERCOPY_FUNC raw_copy_to_user #define ST1(p, v) _ST((p), st1, (v)) #define ST2(p, v) _ST((p), st2, (v)) #define ST4(p, v) _ST((p), st4, (v)) @@ -62,7 +62,7 @@ #define LD8 LD #include "memcpy_64.c" -#define USERCOPY_FUNC __copy_from_user_inatomic +#define USERCOPY_FUNC raw_copy_from_user #define ST1 ST #define ST2 ST #define ST4 ST @@ -73,7 +73,7 @@ #define LD8(p) _LD((p), ld) #include "memcpy_64.c" -#define USERCOPY_FUNC __copy_in_user_inatomic +#define USERCOPY_FUNC raw_copy_in_user #define ST1(p, v) _ST((p), st1, (v)) #define ST2(p, v) _ST((p), st2, (v)) #define ST4(p, v) _ST((p), st4, (v)) @@ -83,12 +83,3 @@ #define LD4(p) _LD((p), ld4u) #define LD8(p) _LD((p), ld) #include "memcpy_64.c" - -unsigned long __copy_from_user_zeroing(void *to, const void __user *from, - unsigned long n) -{ - unsigned long rc = __copy_from_user_inatomic(to, from, n); - if (unlikely(rc)) - memset(to + n - rc, 0, rc); - return rc; -} diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index fd443852103c..ed9c5b5ff028 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common @@ -50,11 +50,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config GENERIC_BUG - bool - default y - depends on BUG - config HZ int default 100 diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index e9d42aab76dc..50a32c33d729 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -6,6 +6,7 @@ generic-y += delay.h generic-y += device.h generic-y += emergency-restart.h generic-y += exec.h +generic-y += extable.h generic-y += ftrace.h generic-y += futex.h generic-y += hardirq.h diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h index 94ac2739918c..b668e351fd6c 100644 --- a/arch/um/include/asm/mmu_context.h +++ b/arch/um/include/asm/mmu_context.h @@ -37,12 +37,6 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, return true; } -static inline bool arch_pte_access_permitted(pte_t pte, bool write) -{ - /* by default, allow everything */ - return true; -} - /* * end asm-generic/mm_hooks.h functions */ diff --git a/arch/um/include/asm/pgtable-2level.h b/arch/um/include/asm/pgtable-2level.h index cfbe59752469..179c0ea87a0c 100644 --- a/arch/um/include/asm/pgtable-2level.h +++ b/arch/um/include/asm/pgtable-2level.h @@ -8,6 +8,7 @@ #ifndef __UM_PGTABLE_2LEVEL_H #define __UM_PGTABLE_2LEVEL_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> /* PGDIR_SHIFT determines what a third-level page table entry can map */ diff --git a/arch/um/include/asm/pgtable-3level.h b/arch/um/include/asm/pgtable-3level.h index bae8523a162f..c4d876dfb9ac 100644 --- a/arch/um/include/asm/pgtable-3level.h +++ b/arch/um/include/asm/pgtable-3level.h @@ -7,6 +7,7 @@ #ifndef __UM_PGTABLE_3LEVEL_H #define __UM_PGTABLE_3LEVEL_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> /* PGDIR_SHIFT determines what a third-level page table entry can map */ diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index 3705620ca298..cc00fc50768f 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h @@ -7,7 +7,6 @@ #ifndef __UM_UACCESS_H #define __UM_UACCESS_H -#include <asm/thread_info.h> #include <asm/elf.h> #define __under_task_size(addr, size) \ @@ -22,8 +21,8 @@ #define __addr_range_nowrap(addr, size) \ ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) -extern long __copy_from_user(void *to, const void __user *from, unsigned long n); -extern long __copy_to_user(void __user *to, const void *from, unsigned long n); +extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n); +extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n); extern long __strncpy_from_user(char *dst, const char __user *src, long count); extern long __strnlen_user(const void __user *str, long len); extern unsigned long __clear_user(void __user *mem, unsigned long len); @@ -32,12 +31,10 @@ static inline int __access_ok(unsigned long addr, unsigned long size); /* Teach asm-generic/uaccess.h that we have C functions for these. */ #define __access_ok __access_ok #define __clear_user __clear_user -#define __copy_to_user __copy_to_user -#define __copy_from_user __copy_from_user #define __strnlen_user __strnlen_user #define __strncpy_from_user __strncpy_from_user -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER #include <asm-generic/uaccess.h> @@ -46,7 +43,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size) return __addr_range_nowrap(addr, size) && (__under_task_size(addr, size) || __access_ok_vsyscall(addr, size) || - segment_eq(get_fs(), KERNEL_DS)); + uaccess_kernel()); } #endif diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index de5d572225f3..cd1fa97776c3 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -302,8 +302,8 @@ extern int ignore_sigio_fd(int fd); extern void maybe_sigio_broken(int fd, int read); extern void sigio_broken(int fd, int read); -/* sys-x86_64/prctl.c */ -extern int os_arch_prctl(int pid, int code, unsigned long *addr); +/* prctl.c */ +extern int os_arch_prctl(int pid, int option, unsigned long *arg2); /* tty.c */ extern int get_pty(void); diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 85ac8adb069b..d450797a3a7c 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -139,16 +139,16 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) return 0; } -long __copy_from_user(void *to, const void __user *from, unsigned long n) +unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - if (segment_eq(get_fs(), KERNEL_DS)) { + if (uaccess_kernel()) { memcpy(to, (__force void*)from, n); return 0; } return buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to); } -EXPORT_SYMBOL(__copy_from_user); +EXPORT_SYMBOL(raw_copy_from_user); static int copy_chunk_to_user(unsigned long to, int len, void *arg) { @@ -159,16 +159,16 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) return 0; } -long __copy_to_user(void __user *to, const void *from, unsigned long n) +unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - if (segment_eq(get_fs(), KERNEL_DS)) { + if (uaccess_kernel()) { memcpy((__force void *) to, from, n); return 0; } return buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from); } -EXPORT_SYMBOL(__copy_to_user); +EXPORT_SYMBOL(raw_copy_to_user); static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) { @@ -189,7 +189,7 @@ long __strncpy_from_user(char *dst, const char __user *src, long count) long n; char *ptr = dst; - if (segment_eq(get_fs(), KERNEL_DS)) { + if (uaccess_kernel()) { strncpy(dst, (__force void *) src, count); return strnlen(dst, count); } @@ -210,7 +210,7 @@ static int clear_chunk(unsigned long addr, int len, void *unused) unsigned long __clear_user(void __user *mem, unsigned long len) { - if (segment_eq(get_fs(), KERNEL_DS)) { + if (uaccess_kernel()) { memset((__force void*)mem, 0, len); return 0; } @@ -235,7 +235,7 @@ long __strnlen_user(const void __user *str, long len) { int count = 0, n; - if (segment_eq(get_fs(), KERNEL_DS)) + if (uaccess_kernel()) return strnlen((__force char*)str, len) + 1; n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index ba87a27d6715..0b034ebbda2a 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -65,7 +65,9 @@ static struct clock_event_device timer_clockevent = { .set_next_event = itimer_next_event, .shift = 0, .max_delta_ns = 0xffffffff, - .min_delta_ns = TIMER_MIN_DELTA, //microsecond resolution should be enough for anyone, same as 640K RAM + .max_delta_ticks = 0xffffffff, + .min_delta_ns = TIMER_MIN_DELTA, + .min_delta_ticks = TIMER_MIN_DELTA, // microsecond resolution should be enough for anyone, same as 640K RAM .irq = 0, .mult = 1, }; diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 84205fe1cd79..e9ad511c1043 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -10,6 +10,7 @@ generic-y += div64.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fb.h generic-y += fcntl.h generic-y += ftrace.h diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h index 62dfc644c908..59b06b48f27d 100644 --- a/arch/unicore32/include/asm/mmu_context.h +++ b/arch/unicore32/include/asm/mmu_context.h @@ -103,10 +103,4 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, /* by default, allow everything */ return true; } - -static inline bool arch_pte_access_permitted(pte_t pte, bool write) -{ - /* by default, allow everything */ - return true; -} #endif diff --git a/arch/unicore32/include/asm/pgtable.h b/arch/unicore32/include/asm/pgtable.h index 818d0f5598e3..a4f2bef37e70 100644 --- a/arch/unicore32/include/asm/pgtable.h +++ b/arch/unicore32/include/asm/pgtable.h @@ -12,6 +12,7 @@ #ifndef __UNICORE_PGTABLE_H__ #define __UNICORE_PGTABLE_H__ +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #include <asm/cpu-single.h> diff --git a/arch/unicore32/include/asm/uaccess.h b/arch/unicore32/include/asm/uaccess.h index 897e11ad8124..1d55f2f83759 100644 --- a/arch/unicore32/include/asm/uaccess.h +++ b/arch/unicore32/include/asm/uaccess.h @@ -12,35 +12,30 @@ #ifndef __UNICORE_UACCESS_H__ #define __UNICORE_UACCESS_H__ -#include <linux/thread_info.h> -#include <linux/errno.h> - #include <asm/memory.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 __kernel_ok (uaccess_kernel()) #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); +raw_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); +raw_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); +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER #include <asm-generic/uaccess.h> -extern int fixup_exception(struct pt_regs *regs); - #endif /* __UNICORE_UACCESS_H__ */ diff --git a/arch/unicore32/kernel/ksyms.c b/arch/unicore32/kernel/ksyms.c index 0323528a80fd..dcc72ee1fcdb 100644 --- a/arch/unicore32/kernel/ksyms.c +++ b/arch/unicore32/kernel/ksyms.c @@ -46,8 +46,8 @@ EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(copy_page); -EXPORT_SYMBOL(__copy_from_user); -EXPORT_SYMBOL(__copy_to_user); +EXPORT_SYMBOL(raw_copy_from_user); +EXPORT_SYMBOL(raw_copy_to_user); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(__ashldi3); diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index d22c1dc7e39e..ddaf78ae6854 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c @@ -178,7 +178,7 @@ void __show_regs(struct pt_regs *regs) buf, interrupts_enabled(regs) ? "n" : "ff", fast_interrupts_enabled(regs) ? "n" : "ff", processor_modes[processor_mode(regs)], - segment_eq(get_fs(), get_ds()) ? "kernel" : "user"); + uaccess_kernel() ? "kernel" : "user"); { unsigned int ctrl; diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c index fceaa673f861..c6b3fa3ee0b6 100644 --- a/arch/unicore32/kernel/time.c +++ b/arch/unicore32/kernel/time.c @@ -91,8 +91,10 @@ void __init time_init(void) ckevt_puv3_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_puv3_osmr0); + ckevt_puv3_osmr0.max_delta_ticks = 0x7fffffff; ckevt_puv3_osmr0.min_delta_ns = clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_puv3_osmr0) + 1; + ckevt_puv3_osmr0.min_delta_ticks = MIN_OSCR_DELTA * 2; ckevt_puv3_osmr0.cpumask = cpumask_of(0); setup_irq(IRQ_TIMER0, &puv3_timer_irq); diff --git a/arch/unicore32/lib/copy_from_user.S b/arch/unicore32/lib/copy_from_user.S index ab0767ea5dbd..5f80fcbe8631 100644 --- a/arch/unicore32/lib/copy_from_user.S +++ b/arch/unicore32/lib/copy_from_user.S @@ -16,7 +16,7 @@ /* * Prototype: * - * size_t __copy_from_user(void *to, const void *from, size_t n) + * size_t raw_copy_from_user(void *to, const void *from, size_t n) * * Purpose: * @@ -87,22 +87,18 @@ .text -ENTRY(__copy_from_user) +ENTRY(raw_copy_from_user) #include "copy_template.S" -ENDPROC(__copy_from_user) +ENDPROC(raw_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 + ldm.w (r1, r2, r3), [sp]+ + sub r0, r0, r1 + rsub r0, r0, r2 copy_abort_end .popsection diff --git a/arch/unicore32/lib/copy_to_user.S b/arch/unicore32/lib/copy_to_user.S index 6e22151c840d..857c6816ffe7 100644 --- a/arch/unicore32/lib/copy_to_user.S +++ b/arch/unicore32/lib/copy_to_user.S @@ -16,7 +16,7 @@ /* * Prototype: * - * size_t __copy_to_user(void *to, const void *from, size_t n) + * size_t raw_copy_to_user(void *to, const void *from, size_t n) * * Purpose: * @@ -79,11 +79,11 @@ .text -WEAK(__copy_to_user) +WEAK(raw_copy_to_user) #include "copy_template.S" -ENDPROC(__copy_to_user) +ENDPROC(raw_copy_to_user) .pushsection .fixup,"ax" .align 0 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2a26852c11b6..cd18994a9555 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -98,7 +98,6 @@ config X86 select HAVE_ACPI_APEI_NMI if ACPI select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL - select HAVE_ARCH_HARDENED_USERCOPY select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP @@ -106,6 +105,7 @@ config X86 select HAVE_ARCH_KMEMCHECK select HAVE_ARCH_MMAP_RND_BITS if MMU select HAVE_ARCH_MMAP_RND_COMPAT_BITS if MMU && COMPAT + select HAVE_ARCH_COMPAT_MMAP_BASES if MMU && COMPAT select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE @@ -127,7 +127,7 @@ config X86 select HAVE_EBPF_JIT if X86_64 select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_EXIT_THREAD - select HAVE_FENTRY if X86_64 + select HAVE_FENTRY if X86_64 || DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER @@ -291,6 +291,7 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC config KASAN_SHADOW_OFFSET hex depends on KASAN + default 0xdff8000000000000 if X86_5LEVEL default 0xdffffc0000000000 config HAVE_INTEL_TXT @@ -1044,6 +1045,14 @@ config X86_MCE The action the kernel takes depends on the severity of the problem, ranging from warning messages to halting the machine. +config X86_MCELOG_LEGACY + bool "Support for deprecated /dev/mcelog character device" + depends on X86_MCE + ---help--- + Enable support for /dev/mcelog which is needed by the old mcelog + userspace logging daemon. Consider switching to the new generation + rasdaemon solution. + config X86_MCE_INTEL def_bool y prompt "Intel MCE features" @@ -1073,7 +1082,7 @@ config X86_MCE_THRESHOLD def_bool y config X86_MCE_INJECT - depends on X86_MCE && X86_LOCAL_APIC + depends on X86_MCE && X86_LOCAL_APIC && X86_MCELOG_LEGACY tristate "Machine check injector support" ---help--- Provide support for injecting machine checks for testing purposes. @@ -1967,7 +1976,7 @@ config RELOCATABLE config RANDOMIZE_BASE bool "Randomize the address of the kernel image (KASLR)" depends on RELOCATABLE - default n + default y ---help--- In support of Kernel Address Space Layout Randomization (KASLR), this randomizes the physical address at which the kernel image @@ -1997,7 +2006,7 @@ config RANDOMIZE_BASE theoretically possible, but the implementations are further limited due to memory layouts. - If unsure, say N. + If unsure, say Y. # Relocation on x86 needs some additional build support config X86_NEED_RELOCS @@ -2046,7 +2055,7 @@ config RANDOMIZE_MEMORY configuration have in average 30,000 different possible virtual addresses for each memory section. - If unsure, say N. + If unsure, say Y. config RANDOMIZE_MEMORY_PHYSICAL_PADDING hex "Physical memory mapping padding" if EXPERT diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 63c1d13aaf9f..fcb7604172ce 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -5,6 +5,9 @@ config TRACE_IRQFLAGS_SUPPORT source "lib/Kconfig.debug" +config EARLY_PRINTK_USB + bool + config X86_VERBOSE_BOOTUP bool "Enable verbose x86 bootup info messages" default y @@ -23,19 +26,20 @@ config EARLY_PRINTK This is useful for kernel debugging when your machine crashes very early before the console code is initialized. For normal operation it is not recommended because it looks ugly and doesn't cooperate - with klogd/syslogd or the X server. You should normally N here, + with klogd/syslogd or the X server. You should normally say N here, unless you want to debug such a crash. config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" depends on EARLY_PRINTK && PCI + select EARLY_PRINTK_USB ---help--- Write kernel log output directly into the EHCI debug port. This is useful for kernel debugging when your machine crashes very early before the console code is initialized. For normal operation it is not recommended because it looks ugly and doesn't cooperate - with klogd/syslogd or the X server. You should normally N here, + with klogd/syslogd or the X server. You should normally say N here, unless you want to debug such a crash. You need usb debug device. config EARLY_PRINTK_EFI @@ -48,6 +52,25 @@ config EARLY_PRINTK_EFI This is useful for kernel debugging when your machine crashes very early before the console code is initialized. +config EARLY_PRINTK_USB_XDBC + bool "Early printk via the xHCI debug port" + depends on EARLY_PRINTK && PCI + select EARLY_PRINTK_USB + ---help--- + Write kernel log output directly into the xHCI debug port. + + One use for this feature is kernel debugging, for example when your + machine crashes very early before the regular console code is + initialized. Other uses include simpler, lockless logging instead of + a full-blown printk console driver + klogd. + + For normal production environments this is normally not recommended, + because it doesn't feed events into klogd/syslogd and doesn't try to + print anything on the screen. + + You should normally say N here, unless you want to debug early + crashes or need a very simple printk logging facility. + config X86_PTDUMP_CORE def_bool n diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 2d449337a360..4430dd489620 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -88,10 +88,10 @@ else KBUILD_CFLAGS += -m64 # Align jump targets to 1 byte, not the default 16 bytes: - KBUILD_CFLAGS += -falign-jumps=1 + KBUILD_CFLAGS += $(call cc-option,-falign-jumps=1) # Pack loops tightly as well: - KBUILD_CFLAGS += -falign-loops=1 + KBUILD_CFLAGS += $(call cc-option,-falign-loops=1) # Don't autogenerate traditional x87 instructions KBUILD_CFLAGS += $(call cc-option,-mno-80387) @@ -120,10 +120,6 @@ else # -funit-at-a-time shrinks the kernel .text considerably # unfortunately it makes reading oopses harder. KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time) - - # this works around some issues with generating unwind tables in older gccs - # newer gccs do it by default - KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args) endif ifdef CONFIG_X86_X32 @@ -147,6 +143,45 @@ ifeq ($(CONFIG_KMEMCHECK),y) KBUILD_CFLAGS += $(call cc-option,-fno-builtin-memcpy) endif +# +# If the function graph tracer is used with mcount instead of fentry, +# '-maccumulate-outgoing-args' is needed to prevent a GCC bug +# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42109) +# +ifdef CONFIG_FUNCTION_GRAPH_TRACER + ifndef CONFIG_HAVE_FENTRY + ACCUMULATE_OUTGOING_ARGS := 1 + else + ifeq ($(call cc-option-yn, -mfentry), n) + ACCUMULATE_OUTGOING_ARGS := 1 + + # GCC ignores '-maccumulate-outgoing-args' when used with '-Os'. + # If '-Os' is enabled, disable it and print a warning. + ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE + undefine CONFIG_CC_OPTIMIZE_FOR_SIZE + $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE. Your compiler does not have -mfentry so you cannot optimize for size with CONFIG_FUNCTION_GRAPH_TRACER.) + endif + + endif + endif +endif + +# +# Jump labels need '-maccumulate-outgoing-args' for gcc < 4.5.2 to prevent a +# GCC bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46226). There's no way +# to test for this bug at compile-time because the test case needs to execute, +# which is a no-go for cross compilers. So check the GCC version instead. +# +ifdef CONFIG_JUMP_LABEL + ifneq ($(ACCUMULATE_OUTGOING_ARGS), 1) + ACCUMULATE_OUTGOING_ARGS = $(call cc-if-fullversion, -lt, 040502, 1) + endif +endif + +ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1) + KBUILD_CFLAGS += -maccumulate-outgoing-args +endif + # Stackpointer is addressed different for 32 bit and 64 bit x86 sp-$(CONFIG_X86_32) := esp sp-$(CONFIG_X86_64) := rsp diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu index 6647ed49c66c..a45eb15b7cf2 100644 --- a/arch/x86/Makefile_32.cpu +++ b/arch/x86/Makefile_32.cpu @@ -45,24 +45,6 @@ cflags-$(CONFIG_MGEODE_LX) += $(call cc-option,-march=geode,-march=pentium-mmx) # cpu entries cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686)) -# Work around the pentium-mmx code generator madness of gcc4.4.x which -# does stack alignment by generating horrible code _before_ the mcount -# prologue (push %ebp, mov %esp, %ebp) which breaks the function graph -# tracer assumptions. For i686, generic, core2 this is set by the -# compiler anyway -ifeq ($(CONFIG_FUNCTION_GRAPH_TRACER), y) -ADD_ACCUMULATE_OUTGOING_ARGS := y -endif - -# Work around to a bug with asm goto with first implementations of it -# in gcc causing gcc to mess up the push and pop of the stack in some -# uses of asm goto. -ifeq ($(CONFIG_JUMP_LABEL), y) -ADD_ACCUMULATE_OUTGOING_ARGS := y -endif - -cflags-$(ADD_ACCUMULATE_OUTGOING_ARGS) += $(call cc-option,-maccumulate-outgoing-args) - # Bug fix for binutils: this option is required in order to keep # binutils from generating NOPL instructions against our will. ifneq ($(CONFIG_X86_P6_NOP),y) diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 9b42b6d1e902..ef5a9cc66fb8 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h @@ -16,7 +16,7 @@ #ifndef BOOT_BOOT_H #define BOOT_BOOT_H -#define STACK_SIZE 512 /* Minimum number of bytes for stack */ +#define STACK_SIZE 1024 /* Minimum number of bytes for stack */ #ifndef __ASSEMBLY__ diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 801c7a158e55..cbf4b87f55b9 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -9,7 +9,9 @@ #include <linux/efi.h> #include <linux/pci.h> + #include <asm/efi.h> +#include <asm/e820/types.h> #include <asm/setup.h> #include <asm/desc.h> @@ -729,7 +731,7 @@ static void add_e820ext(struct boot_params *params, unsigned long size; e820ext->type = SETUP_E820_EXT; - e820ext->len = nr_entries * sizeof(struct e820entry); + e820ext->len = nr_entries * sizeof(struct boot_e820_entry); e820ext->next = 0; data = (struct setup_data *)(unsigned long)params->hdr.setup_data; @@ -746,9 +748,9 @@ static void add_e820ext(struct boot_params *params, static efi_status_t setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_size) { - struct e820entry *e820_map = ¶ms->e820_map[0]; + struct boot_e820_entry *entry = params->e820_table; struct efi_info *efi = ¶ms->efi_info; - struct e820entry *prev = NULL; + struct boot_e820_entry *prev = NULL; u32 nr_entries; u32 nr_desc; int i; @@ -773,15 +775,15 @@ static efi_status_t setup_e820(struct boot_params *params, case EFI_MEMORY_MAPPED_IO: case EFI_MEMORY_MAPPED_IO_PORT_SPACE: case EFI_PAL_CODE: - e820_type = E820_RESERVED; + e820_type = E820_TYPE_RESERVED; break; case EFI_UNUSABLE_MEMORY: - e820_type = E820_UNUSABLE; + e820_type = E820_TYPE_UNUSABLE; break; case EFI_ACPI_RECLAIM_MEMORY: - e820_type = E820_ACPI; + e820_type = E820_TYPE_ACPI; break; case EFI_LOADER_CODE: @@ -789,15 +791,15 @@ static efi_status_t setup_e820(struct boot_params *params, case EFI_BOOT_SERVICES_CODE: case EFI_BOOT_SERVICES_DATA: case EFI_CONVENTIONAL_MEMORY: - e820_type = E820_RAM; + e820_type = E820_TYPE_RAM; break; case EFI_ACPI_MEMORY_NVS: - e820_type = E820_NVS; + e820_type = E820_TYPE_NVS; break; case EFI_PERSISTENT_MEMORY: - e820_type = E820_PMEM; + e820_type = E820_TYPE_PMEM; break; default: @@ -811,26 +813,26 @@ static efi_status_t setup_e820(struct boot_params *params, continue; } - if (nr_entries == ARRAY_SIZE(params->e820_map)) { - u32 need = (nr_desc - i) * sizeof(struct e820entry) + + if (nr_entries == ARRAY_SIZE(params->e820_table)) { + u32 need = (nr_desc - i) * sizeof(struct e820_entry) + sizeof(struct setup_data); if (!e820ext || e820ext_size < need) return EFI_BUFFER_TOO_SMALL; /* boot_params map full, switch to e820 extended */ - e820_map = (struct e820entry *)e820ext->data; + entry = (struct boot_e820_entry *)e820ext->data; } - e820_map->addr = d->phys_addr; - e820_map->size = d->num_pages << PAGE_SHIFT; - e820_map->type = e820_type; - prev = e820_map++; + entry->addr = d->phys_addr; + entry->size = d->num_pages << PAGE_SHIFT; + entry->type = e820_type; + prev = entry++; nr_entries++; } - if (nr_entries > ARRAY_SIZE(params->e820_map)) { - u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map); + if (nr_entries > ARRAY_SIZE(params->e820_table)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_table); add_e820ext(params, e820ext, nr_e820ext); nr_entries -= nr_e820ext; @@ -848,7 +850,7 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, unsigned long size; size = sizeof(struct setup_data) + - sizeof(struct e820entry) * nr_desc; + sizeof(struct e820_entry) * nr_desc; if (*e820ext) { efi_call_early(free_pool, *e820ext); @@ -884,9 +886,9 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, if (first) { nr_desc = *map->buff_size / *map->desc_size; - if (nr_desc > ARRAY_SIZE(p->boot_params->e820_map)) { + if (nr_desc > ARRAY_SIZE(p->boot_params->e820_table)) { u32 nr_e820ext = nr_desc - - ARRAY_SIZE(p->boot_params->e820_map); + ARRAY_SIZE(p->boot_params->e820_table); status = alloc_e820ext(nr_e820ext, &p->e820ext, &p->e820ext_size); diff --git a/arch/x86/boot/compressed/error.c b/arch/x86/boot/compressed/error.c index 6248740b68b5..31922023de49 100644 --- a/arch/x86/boot/compressed/error.c +++ b/arch/x86/boot/compressed/error.c @@ -4,6 +4,7 @@ * memcpy() and memmove() are defined for the compressed boot environment. */ #include "misc.h" +#include "error.h" void warn(char *m) { diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 8b7c9e75edcb..54c24f0a43d3 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -426,7 +426,7 @@ static unsigned long slots_fetch_random(void) return 0; } -static void process_e820_entry(struct e820entry *entry, +static void process_e820_entry(struct boot_e820_entry *entry, unsigned long minimum, unsigned long image_size) { @@ -435,7 +435,7 @@ static void process_e820_entry(struct e820entry *entry, unsigned long start_orig; /* Skip non-RAM entries. */ - if (entry->type != E820_RAM) + if (entry->type != E820_TYPE_RAM) return; /* On 32-bit, ignore entries entirely above our maximum. */ @@ -518,7 +518,7 @@ static unsigned long find_random_phys_addr(unsigned long minimum, /* Verify potential e820 positions, appending to slots list. */ for (i = 0; i < boot_params->e820_entries; i++) { - process_e820_entry(&boot_params->e820_map[i], minimum, + process_e820_entry(&boot_params->e820_table[i], minimum, image_size); if (slot_area_index == MAX_SLOT_AREA) { debug_putstr("Aborted e820 scan (slot_areas full)!\n"); @@ -597,10 +597,17 @@ void choose_random_location(unsigned long input, add_identity_map(random_addr, output_size); *output = random_addr; } + + /* + * This loads the identity mapping page table. + * This should only be done if a new physical address + * is found for the kernel, otherwise we should keep + * the old page table to make it be like the "nokaslr" + * case. + */ + finalize_identity_maps(); } - /* This actually loads the identity pagetable on x86_64. */ - finalize_identity_maps(); /* Pick random virtual address starting from LOAD_PHYSICAL_ADDR. */ if (IS_ENABLED(CONFIG_X86_64)) diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 4ad7d70e8739..8f0c4c9fc904 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -44,6 +44,15 @@ static const u32 req_flags[NCAPINTS] = 0, /* REQUIRED_MASK5 not implemented in this file */ REQUIRED_MASK6, 0, /* REQUIRED_MASK7 not implemented in this file */ + 0, /* REQUIRED_MASK8 not implemented in this file */ + 0, /* REQUIRED_MASK9 not implemented in this file */ + 0, /* REQUIRED_MASK10 not implemented in this file */ + 0, /* REQUIRED_MASK11 not implemented in this file */ + 0, /* REQUIRED_MASK12 not implemented in this file */ + 0, /* REQUIRED_MASK13 not implemented in this file */ + 0, /* REQUIRED_MASK14 not implemented in this file */ + 0, /* REQUIRED_MASK15 not implemented in this file */ + REQUIRED_MASK16, }; #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c index 6687ab953257..9e77c23c2422 100644 --- a/arch/x86/boot/cpuflags.c +++ b/arch/x86/boot/cpuflags.c @@ -70,16 +70,19 @@ int has_eflag(unsigned long mask) # define EBX_REG "=b" #endif -static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d) +static inline void cpuid_count(u32 id, u32 count, + u32 *a, u32 *b, u32 *c, u32 *d) { asm volatile(".ifnc %%ebx,%3 ; movl %%ebx,%3 ; .endif \n\t" "cpuid \n\t" ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif \n\t" : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b) - : "a" (id) + : "a" (id), "c" (count) ); } +#define cpuid(id, a, b, c, d) cpuid_count(id, 0, a, b, c, d) + void get_cpuflags(void) { u32 max_intel_level, max_amd_level; @@ -108,6 +111,11 @@ void get_cpuflags(void) cpu.model += ((tfms >> 16) & 0xf) << 4; } + if (max_intel_level >= 0x00000007) { + cpuid_count(0x00000007, 0, &ignored, &ignored, + &cpu.flags[16], &ignored); + } + cpuid(0x80000000, &max_amd_level, &ignored, &ignored, &ignored); diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 3dd5be33aaa7..2ed8f0c25def 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -18,7 +18,6 @@ #include <asm/segment.h> #include <generated/utsrelease.h> #include <asm/boot.h> -#include <asm/e820.h> #include <asm/page_types.h> #include <asm/setup.h> #include <asm/bootparam.h> diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c index db75d07c3645..d9c28c87e477 100644 --- a/arch/x86/boot/memory.c +++ b/arch/x86/boot/memory.c @@ -21,8 +21,8 @@ static int detect_memory_e820(void) { int count = 0; struct biosregs ireg, oreg; - struct e820entry *desc = boot_params.e820_map; - static struct e820entry buf; /* static so it is zeroed */ + struct boot_e820_entry *desc = boot_params.e820_table; + static struct boot_e820_entry buf; /* static so it is zeroed */ initregs(&ireg); ireg.ax = 0xe820; @@ -66,7 +66,7 @@ static int detect_memory_e820(void) *desc++ = buf; count++; - } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map)); + } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_table)); return boot_params.e820_entries = count; } diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 5fa6ee2c2dde..6cf79e1a6830 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -57,6 +57,8 @@ CONFIG_EFI=y CONFIG_HZ_1000=y CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_MEMORY=y # CONFIG_COMPAT_VDSO is not set CONFIG_HIBERNATION=y CONFIG_PM_DEBUG=y diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 7ef4a099defc..de45f57b410d 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -55,6 +55,8 @@ CONFIG_EFI=y CONFIG_HZ_1000=y CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_MEMORY=y # CONFIG_COMPAT_VDSO is not set CONFIG_HIBERNATION=y CONFIG_PM_DEBUG=y @@ -176,6 +178,7 @@ CONFIG_E1000E=y CONFIG_SKY2=y CONFIG_FORCEDETH=y CONFIG_8139TOO=y +CONFIG_R8169=y CONFIG_FDDI=y CONFIG_INPUT_POLLDEV=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set diff --git a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S index a916c4a61165..5f6a5af9c489 100644 --- a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S +++ b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S @@ -65,7 +65,6 @@ #include <linux/linkage.h> #include <asm/inst.h> -#define CONCAT(a,b) a##b #define VMOVDQ vmovdqu #define xdata0 %xmm0 @@ -92,8 +91,6 @@ #define num_bytes %r8 #define tmp %r10 -#define DDQ(i) CONCAT(ddq_add_,i) -#define XMM(i) CONCAT(%xmm, i) #define DDQ_DATA 0 #define XDATA 1 #define KEY_128 1 @@ -131,12 +128,12 @@ ddq_add_8: /* generate a unique variable for ddq_add_x */ .macro setddq n - var_ddq_add = DDQ(\n) + var_ddq_add = ddq_add_\n .endm /* generate a unique variable for xmm register */ .macro setxdata n - var_xdata = XMM(\n) + var_xdata = %xmm\n .endm /* club the numeric 'id' to the symbol 'name' */ diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c index aa76cad9d262..af4840ab2a3d 100644 --- a/arch/x86/crypto/camellia_glue.c +++ b/arch/x86/crypto/camellia_glue.c @@ -1522,7 +1522,7 @@ static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct camellia_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - be128 buf[2 * 4]; + le128 buf[2 * 4]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), @@ -1540,7 +1540,7 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct camellia_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - be128 buf[2 * 4]; + le128 buf[2 * 4]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), diff --git a/arch/x86/crypto/glue_helper.c b/arch/x86/crypto/glue_helper.c index 260a060d7275..24ac9fad832d 100644 --- a/arch/x86/crypto/glue_helper.c +++ b/arch/x86/crypto/glue_helper.c @@ -27,6 +27,7 @@ #include <linux/module.h> #include <crypto/b128ops.h> +#include <crypto/gf128mul.h> #include <crypto/internal/skcipher.h> #include <crypto/lrw.h> #include <crypto/xts.h> @@ -457,7 +458,7 @@ void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src, le128 *iv, le128 ivblk = *iv; /* generate next IV */ - le128_gf128mul_x_ble(iv, &ivblk); + gf128mul_x_ble(iv, &ivblk); /* CC <- T xor C */ u128_xor(dst, src, (u128 *)&ivblk); diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 644f97ab8cac..ac0e831943f5 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -328,7 +328,7 @@ static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - be128 buf[SERPENT_PARALLEL_BLOCKS]; + le128 buf[SERPENT_PARALLEL_BLOCKS]; struct crypt_priv crypt_ctx = { .ctx = &ctx->crypt_ctx, .fpu_enabled = false, @@ -355,7 +355,7 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - be128 buf[SERPENT_PARALLEL_BLOCKS]; + le128 buf[SERPENT_PARALLEL_BLOCKS]; struct crypt_priv crypt_ctx = { .ctx = &ctx->crypt_ctx, .fpu_enabled = false, diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 2ebb5e9789f3..243e90a4b5d9 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -296,7 +296,7 @@ static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - be128 buf[3]; + le128 buf[3]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), @@ -314,7 +314,7 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - be128 buf[3]; + le128 buf[3]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 57f7ec35216e..50bc26949e9e 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -35,16 +35,13 @@ #include <asm/errno.h> #include <asm/segment.h> #include <asm/smp.h> -#include <asm/page_types.h> #include <asm/percpu.h> #include <asm/processor-flags.h> -#include <asm/ftrace.h> #include <asm/irq_vectors.h> #include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #include <asm/asm.h> #include <asm/smap.h> -#include <asm/export.h> #include <asm/frame.h> .section .entry.text, "ax" @@ -585,7 +582,7 @@ ENTRY(iret_exc ) * will soon execute iret and the tracer was already set to * the irqstate after the IRET: */ - DISABLE_INTERRUPTS(CLBR_EAX) + DISABLE_INTERRUPTS(CLBR_ANY) lss (%esp), %esp /* switch to espfix segment */ jmp .Lrestore_nocheck #endif @@ -886,172 +883,6 @@ BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, #endif /* CONFIG_HYPERV */ -#ifdef CONFIG_FUNCTION_TRACER -#ifdef CONFIG_DYNAMIC_FTRACE - -ENTRY(mcount) - ret -END(mcount) - -ENTRY(ftrace_caller) - pushl %eax - pushl %ecx - pushl %edx - pushl $0 /* Pass NULL as regs pointer */ - movl 4*4(%esp), %eax - movl 0x4(%ebp), %edx - movl function_trace_op, %ecx - subl $MCOUNT_INSN_SIZE, %eax - -.globl ftrace_call -ftrace_call: - call ftrace_stub - - addl $4, %esp /* skip NULL pointer */ - popl %edx - popl %ecx - popl %eax -.Lftrace_ret: -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -.globl ftrace_graph_call -ftrace_graph_call: - jmp ftrace_stub -#endif - -/* This is weak to keep gas from relaxing the jumps */ -WEAK(ftrace_stub) - ret -END(ftrace_caller) - -ENTRY(ftrace_regs_caller) - pushf /* push flags before compare (in cs location) */ - - /* - * i386 does not save SS and ESP when coming from kernel. - * Instead, to get sp, ®s->sp is used (see ptrace.h). - * Unfortunately, that means eflags must be at the same location - * as the current return ip is. We move the return ip into the - * ip location, and move flags into the return ip location. - */ - pushl 4(%esp) /* save return ip into ip slot */ - - pushl $0 /* Load 0 into orig_ax */ - pushl %gs - pushl %fs - pushl %es - pushl %ds - pushl %eax - pushl %ebp - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - - movl 13*4(%esp), %eax /* Get the saved flags */ - movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ - /* clobbering return ip */ - movl $__KERNEL_CS, 13*4(%esp) - - movl 12*4(%esp), %eax /* Load ip (1st parameter) */ - subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ - movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ - movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ - pushl %esp /* Save pt_regs as 4th parameter */ - -GLOBAL(ftrace_regs_call) - call ftrace_stub - - addl $4, %esp /* Skip pt_regs */ - movl 14*4(%esp), %eax /* Move flags back into cs */ - movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ - movl 12*4(%esp), %eax /* Get return ip from regs->ip */ - movl %eax, 14*4(%esp) /* Put return ip back for ret */ - - popl %ebx - popl %ecx - popl %edx - popl %esi - popl %edi - popl %ebp - popl %eax - popl %ds - popl %es - popl %fs - popl %gs - addl $8, %esp /* Skip orig_ax and ip */ - popf /* Pop flags at end (no addl to corrupt flags) */ - jmp .Lftrace_ret - - popf - jmp ftrace_stub -#else /* ! CONFIG_DYNAMIC_FTRACE */ - -ENTRY(mcount) - cmpl $__PAGE_OFFSET, %esp - jb ftrace_stub /* Paging not enabled yet? */ - - cmpl $ftrace_stub, ftrace_trace_function - jnz .Ltrace -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - cmpl $ftrace_stub, ftrace_graph_return - jnz ftrace_graph_caller - - cmpl $ftrace_graph_entry_stub, ftrace_graph_entry - jnz ftrace_graph_caller -#endif -.globl ftrace_stub -ftrace_stub: - ret - - /* taken from glibc */ -.Ltrace: - pushl %eax - pushl %ecx - pushl %edx - movl 0xc(%esp), %eax - movl 0x4(%ebp), %edx - subl $MCOUNT_INSN_SIZE, %eax - - call *ftrace_trace_function - - popl %edx - popl %ecx - popl %eax - jmp ftrace_stub -END(mcount) -#endif /* CONFIG_DYNAMIC_FTRACE */ -EXPORT_SYMBOL(mcount) -#endif /* CONFIG_FUNCTION_TRACER */ - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -ENTRY(ftrace_graph_caller) - pushl %eax - pushl %ecx - pushl %edx - movl 0xc(%esp), %eax - lea 0x4(%ebp), %edx - movl (%ebp), %ecx - subl $MCOUNT_INSN_SIZE, %eax - call prepare_ftrace_return - popl %edx - popl %ecx - popl %eax - ret -END(ftrace_graph_caller) - -.globl return_to_handler -return_to_handler: - pushl %eax - pushl %edx - movl %ebp, %eax - call ftrace_return_to_handler - movl %eax, %ecx - popl %edx - popl %eax - jmp *%ecx -#endif - #ifdef CONFIG_TRACING ENTRY(trace_page_fault) ASM_CLAC diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 044d18ebc43c..607d72c4a485 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -212,7 +212,7 @@ entry_SYSCALL_64_fastpath: * If we see that no exit work is required (which we are required * to check with IRQs off), then we can go straight to SYSRET64. */ - DISABLE_INTERRUPTS(CLBR_NONE) + DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF movq PER_CPU_VAR(current_task), %r11 testl $_TIF_ALLWORK_MASK, TASK_TI_flags(%r11) @@ -233,7 +233,7 @@ entry_SYSCALL_64_fastpath: * raise(3) will trigger this, for example. IRQs are off. */ TRACE_IRQS_ON - ENABLE_INTERRUPTS(CLBR_NONE) + ENABLE_INTERRUPTS(CLBR_ANY) SAVE_EXTRA_REGS movq %rsp, %rdi call syscall_return_slowpath /* returns with IRQs disabled */ @@ -265,12 +265,9 @@ return_from_SYSCALL_64: * * If width of "canonical tail" ever becomes variable, this will need * to be updated to remain correct on both old and new CPUs. + * + * Change top 16 bits to be the sign-extension of 47th bit */ - .ifne __VIRTUAL_MASK_SHIFT - 47 - .error "virtual address width changed -- SYSRET checks need update" - .endif - - /* Change top 16 bits to be the sign-extension of 47th bit */ shl $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx sar $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx @@ -343,7 +340,7 @@ ENTRY(stub_ptregs_64) * Called from fast path -- disable IRQs again, pop return address * and jump to slow path */ - DISABLE_INTERRUPTS(CLBR_NONE) + DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF popq %rax jmp entry_SYSCALL64_slow_path @@ -518,7 +515,7 @@ common_interrupt: interrupt do_IRQ /* 0(%rsp): old RSP */ ret_from_intr: - DISABLE_INTERRUPTS(CLBR_NONE) + DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF decl PER_CPU_VAR(irq_count) @@ -1051,7 +1048,7 @@ END(paranoid_entry) * On entry, ebx is "no swapgs" flag (1: don't need swapgs, 0: need it) */ ENTRY(paranoid_exit) - DISABLE_INTERRUPTS(CLBR_NONE) + DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF_DEBUG testl %ebx, %ebx /* swapgs needed? */ jnz paranoid_exit_no_swapgs @@ -1156,10 +1153,9 @@ END(error_entry) * 0: user gsbase is loaded, we need SWAPGS and standard preparation for return to usermode */ ENTRY(error_exit) - movl %ebx, %eax - DISABLE_INTERRUPTS(CLBR_NONE) + DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF - testl %eax, %eax + testl %ebx, %ebx jnz retint_kernel jmp retint_user END(error_exit) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 9ba050fe47f3..448ac2161112 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -226,7 +226,7 @@ 217 i386 pivot_root sys_pivot_root 218 i386 mincore sys_mincore 219 i386 madvise sys_madvise -220 i386 getdents64 sys_getdents64 compat_sys_getdents64 +220 i386 getdents64 sys_getdents64 221 i386 fcntl64 sys_fcntl64 compat_sys_fcntl64 # 222 is unused # 223 is unused @@ -390,3 +390,4 @@ 381 i386 pkey_alloc sys_pkey_alloc 382 i386 pkey_free sys_pkey_free 383 i386 statx sys_statx +384 i386 arch_prctl sys_arch_prctl compat_sys_arch_prctl diff --git a/arch/x86/entry/vdso/vclock_gettime.c b/arch/x86/entry/vdso/vclock_gettime.c index 9d4d6e138311..fa8dbfcf7ed3 100644 --- a/arch/x86/entry/vdso/vclock_gettime.c +++ b/arch/x86/entry/vdso/vclock_gettime.c @@ -17,6 +17,7 @@ #include <asm/unistd.h> #include <asm/msr.h> #include <asm/pvclock.h> +#include <asm/mshyperv.h> #include <linux/math64.h> #include <linux/time.h> #include <linux/kernel.h> @@ -32,6 +33,11 @@ extern u8 pvclock_page __attribute__((visibility("hidden"))); #endif +#ifdef CONFIG_HYPERV_TSCPAGE +extern u8 hvclock_page + __attribute__((visibility("hidden"))); +#endif + #ifndef BUILD_VDSO32 notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) @@ -141,6 +147,20 @@ static notrace u64 vread_pvclock(int *mode) return last; } #endif +#ifdef CONFIG_HYPERV_TSCPAGE +static notrace u64 vread_hvclock(int *mode) +{ + const struct ms_hyperv_tsc_page *tsc_pg = + (const struct ms_hyperv_tsc_page *)&hvclock_page; + u64 current_tick = hv_read_tsc_page(tsc_pg); + + if (current_tick != U64_MAX) + return current_tick; + + *mode = VCLOCK_NONE; + return 0; +} +#endif notrace static u64 vread_tsc(void) { @@ -173,6 +193,10 @@ notrace static inline u64 vgetsns(int *mode) else if (gtod->vclock_mode == VCLOCK_PVCLOCK) cycles = vread_pvclock(mode); #endif +#ifdef CONFIG_HYPERV_TSCPAGE + else if (gtod->vclock_mode == VCLOCK_HVCLOCK) + cycles = vread_hvclock(mode); +#endif else return 0; v = (cycles - gtod->cycle_last) & gtod->mask; diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S index a708aa90b507..8ebb4b6454fe 100644 --- a/arch/x86/entry/vdso/vdso-layout.lds.S +++ b/arch/x86/entry/vdso/vdso-layout.lds.S @@ -25,7 +25,7 @@ SECTIONS * segment. */ - vvar_start = . - 2 * PAGE_SIZE; + vvar_start = . - 3 * PAGE_SIZE; vvar_page = vvar_start; /* Place all vvars at the offsets in asm/vvar.h. */ @@ -36,6 +36,7 @@ SECTIONS #undef EMIT_VVAR pvclock_page = vvar_start + PAGE_SIZE; + hvclock_page = vvar_start + 2 * PAGE_SIZE; . = SIZEOF_HEADERS; diff --git a/arch/x86/entry/vdso/vdso2c.c b/arch/x86/entry/vdso/vdso2c.c index 491020b2826d..0780a443a53b 100644 --- a/arch/x86/entry/vdso/vdso2c.c +++ b/arch/x86/entry/vdso/vdso2c.c @@ -74,6 +74,7 @@ enum { sym_vvar_page, sym_hpet_page, sym_pvclock_page, + sym_hvclock_page, sym_VDSO_FAKE_SECTION_TABLE_START, sym_VDSO_FAKE_SECTION_TABLE_END, }; @@ -82,6 +83,7 @@ const int special_pages[] = { sym_vvar_page, sym_hpet_page, sym_pvclock_page, + sym_hvclock_page, }; struct vdso_sym { @@ -94,6 +96,7 @@ struct vdso_sym required_syms[] = { [sym_vvar_page] = {"vvar_page", true}, [sym_hpet_page] = {"hpet_page", true}, [sym_pvclock_page] = {"pvclock_page", true}, + [sym_hvclock_page] = {"hvclock_page", true}, [sym_VDSO_FAKE_SECTION_TABLE_START] = { "VDSO_FAKE_SECTION_TABLE_START", false }, diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c index 7853b53959cd..3f9d1a83891a 100644 --- a/arch/x86/entry/vdso/vdso32-setup.c +++ b/arch/x86/entry/vdso/vdso32-setup.c @@ -30,8 +30,10 @@ static int __init vdso32_setup(char *s) { vdso32_enabled = simple_strtoul(s, NULL, 0); - if (vdso32_enabled > 1) + if (vdso32_enabled > 1) { pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled\n"); + vdso32_enabled = 0; + } return 1; } @@ -62,13 +64,18 @@ subsys_initcall(sysenter_setup); /* Register vsyscall32 into the ABI table */ #include <linux/sysctl.h> +static const int zero; +static const int one = 1; + static struct ctl_table abi_table2[] = { { .procname = "vsyscall32", .data = &vdso32_enabled, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec + .proc_handler = proc_dointvec_minmax, + .extra1 = (int *)&zero, + .extra2 = (int *)&one, }, {} }; diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 226ca70dc6bd..139ad7726e10 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -22,6 +22,7 @@ #include <asm/page.h> #include <asm/desc.h> #include <asm/cpufeature.h> +#include <asm/mshyperv.h> #if defined(CONFIG_X86_64) unsigned int __read_mostly vdso64_enabled = 1; @@ -121,6 +122,12 @@ static int vvar_fault(const struct vm_special_mapping *sm, vmf->address, __pa(pvti) >> PAGE_SHIFT); } + } else if (sym_offset == image->sym_hvclock_page) { + struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page(); + + if (tsc_pg && vclock_was_used(VCLOCK_HVCLOCK)) + ret = vm_insert_pfn(vma, vmf->address, + vmalloc_to_pfn(tsc_pg)); } if (ret == 0 || ret == -EBUSY) @@ -354,7 +361,7 @@ static void vgetcpu_cpu_init(void *arg) d.p = 1; /* Present */ d.d = 1; /* 32-bit */ - write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S); + write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S); } static int vgetcpu_online(unsigned int cpu) diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index afb222b63cae..c84584bb9402 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c @@ -604,7 +604,7 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx, return &amd_f15_PMC20; } case AMD_EVENT_NB: - /* moved to perf_event_amd_uncore.c */ + /* moved to uncore.c */ return &emptyconstraint; default: return &emptyconstraint; diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index b28200dea715..3641e24fdac5 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c @@ -11,6 +11,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) "perf/amd_iommu: " fmt + #include <linux/perf_event.h> #include <linux/init.h> #include <linux/cpumask.h> @@ -21,44 +23,42 @@ #define COUNTER_SHIFT 16 -#define _GET_BANK(ev) ((u8)(ev->hw.extra_reg.reg >> 8)) -#define _GET_CNTR(ev) ((u8)(ev->hw.extra_reg.reg)) +/* iommu pmu conf masks */ +#define GET_CSOURCE(x) ((x)->conf & 0xFFULL) +#define GET_DEVID(x) (((x)->conf >> 8) & 0xFFFFULL) +#define GET_DOMID(x) (((x)->conf >> 24) & 0xFFFFULL) +#define GET_PASID(x) (((x)->conf >> 40) & 0xFFFFFULL) -/* iommu pmu config masks */ -#define _GET_CSOURCE(ev) ((ev->hw.config & 0xFFULL)) -#define _GET_DEVID(ev) ((ev->hw.config >> 8) & 0xFFFFULL) -#define _GET_PASID(ev) ((ev->hw.config >> 24) & 0xFFFFULL) -#define _GET_DOMID(ev) ((ev->hw.config >> 40) & 0xFFFFULL) -#define _GET_DEVID_MASK(ev) ((ev->hw.extra_reg.config) & 0xFFFFULL) -#define _GET_PASID_MASK(ev) ((ev->hw.extra_reg.config >> 16) & 0xFFFFULL) -#define _GET_DOMID_MASK(ev) ((ev->hw.extra_reg.config >> 32) & 0xFFFFULL) +/* iommu pmu conf1 masks */ +#define GET_DEVID_MASK(x) ((x)->conf1 & 0xFFFFULL) +#define GET_DOMID_MASK(x) (((x)->conf1 >> 16) & 0xFFFFULL) +#define GET_PASID_MASK(x) (((x)->conf1 >> 32) & 0xFFFFFULL) -static struct perf_amd_iommu __perf_iommu; +#define IOMMU_NAME_SIZE 16 struct perf_amd_iommu { + struct list_head list; struct pmu pmu; + struct amd_iommu *iommu; + char name[IOMMU_NAME_SIZE]; u8 max_banks; u8 max_counters; u64 cntr_assign_mask; raw_spinlock_t lock; - const struct attribute_group *attr_groups[4]; }; -#define format_group attr_groups[0] -#define cpumask_group attr_groups[1] -#define events_group attr_groups[2] -#define null_group attr_groups[3] +static LIST_HEAD(perf_amd_iommu_list); /*--------------------------------------------- * sysfs format attributes *---------------------------------------------*/ PMU_FORMAT_ATTR(csource, "config:0-7"); PMU_FORMAT_ATTR(devid, "config:8-23"); -PMU_FORMAT_ATTR(pasid, "config:24-39"); -PMU_FORMAT_ATTR(domid, "config:40-55"); +PMU_FORMAT_ATTR(domid, "config:24-39"); +PMU_FORMAT_ATTR(pasid, "config:40-59"); PMU_FORMAT_ATTR(devid_mask, "config1:0-15"); -PMU_FORMAT_ATTR(pasid_mask, "config1:16-31"); -PMU_FORMAT_ATTR(domid_mask, "config1:32-47"); +PMU_FORMAT_ATTR(domid_mask, "config1:16-31"); +PMU_FORMAT_ATTR(pasid_mask, "config1:32-51"); static struct attribute *iommu_format_attrs[] = { &format_attr_csource.attr, @@ -79,6 +79,10 @@ static struct attribute_group amd_iommu_format_group = { /*--------------------------------------------- * sysfs events attributes *---------------------------------------------*/ +static struct attribute_group amd_iommu_events_group = { + .name = "events", +}; + struct amd_iommu_event_desc { struct kobj_attribute attr; const char *event; @@ -150,30 +154,34 @@ static struct attribute_group amd_iommu_cpumask_group = { /*---------------------------------------------*/ -static int get_next_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu) +static int get_next_avail_iommu_bnk_cntr(struct perf_event *event) { + struct perf_amd_iommu *piommu = container_of(event->pmu, struct perf_amd_iommu, pmu); + int max_cntrs = piommu->max_counters; + int max_banks = piommu->max_banks; + u32 shift, bank, cntr; unsigned long flags; - int shift, bank, cntr, retval; - int max_banks = perf_iommu->max_banks; - int max_cntrs = perf_iommu->max_counters; + int retval; - raw_spin_lock_irqsave(&perf_iommu->lock, flags); + raw_spin_lock_irqsave(&piommu->lock, flags); for (bank = 0, shift = 0; bank < max_banks; bank++) { for (cntr = 0; cntr < max_cntrs; cntr++) { shift = bank + (bank*3) + cntr; - if (perf_iommu->cntr_assign_mask & (1ULL<<shift)) { + if (piommu->cntr_assign_mask & BIT_ULL(shift)) { continue; } else { - perf_iommu->cntr_assign_mask |= (1ULL<<shift); - retval = ((u16)((u16)bank<<8) | (u8)(cntr)); + piommu->cntr_assign_mask |= BIT_ULL(shift); + event->hw.iommu_bank = bank; + event->hw.iommu_cntr = cntr; + retval = 0; goto out; } } } retval = -ENOSPC; out: - raw_spin_unlock_irqrestore(&perf_iommu->lock, flags); + raw_spin_unlock_irqrestore(&piommu->lock, flags); return retval; } @@ -202,8 +210,6 @@ static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu, static int perf_iommu_event_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; - struct perf_amd_iommu *perf_iommu; - u64 config, config1; /* test the event attr type check for PMU enumeration */ if (event->attr.type != event->pmu->type) @@ -225,80 +231,62 @@ static int perf_iommu_event_init(struct perf_event *event) if (event->cpu < 0) return -EINVAL; - perf_iommu = &__perf_iommu; - - if (event->pmu != &perf_iommu->pmu) - return -ENOENT; - - if (perf_iommu) { - config = event->attr.config; - config1 = event->attr.config1; - } else { - return -EINVAL; - } - - /* integrate with iommu base devid (0000), assume one iommu */ - perf_iommu->max_banks = - amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID); - perf_iommu->max_counters = - amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID); - if ((perf_iommu->max_banks == 0) || (perf_iommu->max_counters == 0)) - return -EINVAL; - /* update the hw_perf_event struct with the iommu config data */ - hwc->config = config; - hwc->extra_reg.config = config1; + hwc->conf = event->attr.config; + hwc->conf1 = event->attr.config1; return 0; } +static inline struct amd_iommu *perf_event_2_iommu(struct perf_event *ev) +{ + return (container_of(ev->pmu, struct perf_amd_iommu, pmu))->iommu; +} + static void perf_iommu_enable_event(struct perf_event *ev) { - u8 csource = _GET_CSOURCE(ev); - u16 devid = _GET_DEVID(ev); + struct amd_iommu *iommu = perf_event_2_iommu(ev); + struct hw_perf_event *hwc = &ev->hw; + u8 bank = hwc->iommu_bank; + u8 cntr = hwc->iommu_cntr; u64 reg = 0ULL; - reg = csource; - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_COUNTER_SRC_REG, ®, true); + reg = GET_CSOURCE(hwc); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_COUNTER_SRC_REG, ®); - reg = 0ULL | devid | (_GET_DEVID_MASK(ev) << 32); + reg = GET_DEVID_MASK(hwc); + reg = GET_DEVID(hwc) | (reg << 32); if (reg) - reg |= (1UL << 31); - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_DEVID_MATCH_REG, ®, true); + reg |= BIT(31); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DEVID_MATCH_REG, ®); - reg = 0ULL | _GET_PASID(ev) | (_GET_PASID_MASK(ev) << 32); + reg = GET_PASID_MASK(hwc); + reg = GET_PASID(hwc) | (reg << 32); if (reg) - reg |= (1UL << 31); - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_PASID_MATCH_REG, ®, true); + reg |= BIT(31); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_PASID_MATCH_REG, ®); - reg = 0ULL | _GET_DOMID(ev) | (_GET_DOMID_MASK(ev) << 32); + reg = GET_DOMID_MASK(hwc); + reg = GET_DOMID(hwc) | (reg << 32); if (reg) - reg |= (1UL << 31); - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_DOMID_MATCH_REG, ®, true); + reg |= BIT(31); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DOMID_MATCH_REG, ®); } static void perf_iommu_disable_event(struct perf_event *event) { + struct amd_iommu *iommu = perf_event_2_iommu(event); + struct hw_perf_event *hwc = &event->hw; u64 reg = 0ULL; - amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), - _GET_BANK(event), _GET_CNTR(event), - IOMMU_PC_COUNTER_SRC_REG, ®, true); + amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr, + IOMMU_PC_COUNTER_SRC_REG, ®); } static void perf_iommu_start(struct perf_event *event, int flags) { struct hw_perf_event *hwc = &event->hw; - pr_debug("perf: amd_iommu:perf_iommu_start\n"); if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) return; @@ -306,10 +294,11 @@ static void perf_iommu_start(struct perf_event *event, int flags) hwc->state = 0; if (flags & PERF_EF_RELOAD) { - u64 prev_raw_count = local64_read(&hwc->prev_count); - amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), - _GET_BANK(event), _GET_CNTR(event), - IOMMU_PC_COUNTER_REG, &prev_raw_count, true); + u64 prev_raw_count = local64_read(&hwc->prev_count); + struct amd_iommu *iommu = perf_event_2_iommu(event); + + amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr, + IOMMU_PC_COUNTER_REG, &prev_raw_count); } perf_iommu_enable_event(event); @@ -319,37 +308,30 @@ static void perf_iommu_start(struct perf_event *event, int flags) static void perf_iommu_read(struct perf_event *event) { - u64 count = 0ULL; - u64 prev_raw_count = 0ULL; - u64 delta = 0ULL; + u64 count, prev, delta; struct hw_perf_event *hwc = &event->hw; - pr_debug("perf: amd_iommu:perf_iommu_read\n"); + struct amd_iommu *iommu = perf_event_2_iommu(event); - amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), - _GET_BANK(event), _GET_CNTR(event), - IOMMU_PC_COUNTER_REG, &count, false); + if (amd_iommu_pc_get_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr, + IOMMU_PC_COUNTER_REG, &count)) + return; /* IOMMU pc counter register is only 48 bits */ - count &= 0xFFFFFFFFFFFFULL; + count &= GENMASK_ULL(47, 0); - prev_raw_count = local64_read(&hwc->prev_count); - if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, - count) != prev_raw_count) + prev = local64_read(&hwc->prev_count); + if (local64_cmpxchg(&hwc->prev_count, prev, count) != prev) return; - /* Handling 48-bit counter overflowing */ - delta = (count << COUNTER_SHIFT) - (prev_raw_count << COUNTER_SHIFT); + /* Handle 48-bit counter overflow */ + delta = (count << COUNTER_SHIFT) - (prev << COUNTER_SHIFT); delta >>= COUNTER_SHIFT; local64_add(delta, &event->count); - } static void perf_iommu_stop(struct perf_event *event, int flags) { struct hw_perf_event *hwc = &event->hw; - u64 config; - - pr_debug("perf: amd_iommu:perf_iommu_stop\n"); if (hwc->state & PERF_HES_UPTODATE) return; @@ -361,7 +343,6 @@ static void perf_iommu_stop(struct perf_event *event, int flags) if (hwc->state & PERF_HES_UPTODATE) return; - config = hwc->config; perf_iommu_read(event); hwc->state |= PERF_HES_UPTODATE; } @@ -369,17 +350,12 @@ static void perf_iommu_stop(struct perf_event *event, int flags) static int perf_iommu_add(struct perf_event *event, int flags) { int retval; - struct perf_amd_iommu *perf_iommu = - container_of(event->pmu, struct perf_amd_iommu, pmu); - pr_debug("perf: amd_iommu:perf_iommu_add\n"); event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; /* request an iommu bank/counter */ - retval = get_next_avail_iommu_bnk_cntr(perf_iommu); - if (retval != -ENOSPC) - event->hw.extra_reg.reg = (u16)retval; - else + retval = get_next_avail_iommu_bnk_cntr(event); + if (retval) return retval; if (flags & PERF_EF_START) @@ -390,115 +366,124 @@ static int perf_iommu_add(struct perf_event *event, int flags) static void perf_iommu_del(struct perf_event *event, int flags) { + struct hw_perf_event *hwc = &event->hw; struct perf_amd_iommu *perf_iommu = container_of(event->pmu, struct perf_amd_iommu, pmu); - pr_debug("perf: amd_iommu:perf_iommu_del\n"); perf_iommu_stop(event, PERF_EF_UPDATE); /* clear the assigned iommu bank/counter */ clear_avail_iommu_bnk_cntr(perf_iommu, - _GET_BANK(event), - _GET_CNTR(event)); + hwc->iommu_bank, hwc->iommu_cntr); perf_event_update_userpage(event); } -static __init int _init_events_attrs(struct perf_amd_iommu *perf_iommu) +static __init int _init_events_attrs(void) { - struct attribute **attrs; - struct attribute_group *attr_group; int i = 0, j; + struct attribute **attrs; while (amd_iommu_v2_event_descs[i].attr.attr.name) i++; - attr_group = kzalloc(sizeof(struct attribute *) - * (i + 1) + sizeof(*attr_group), GFP_KERNEL); - if (!attr_group) + attrs = kzalloc(sizeof(struct attribute **) * (i + 1), GFP_KERNEL); + if (!attrs) return -ENOMEM; - attrs = (struct attribute **)(attr_group + 1); for (j = 0; j < i; j++) attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr; - attr_group->name = "events"; - attr_group->attrs = attrs; - perf_iommu->events_group = attr_group; - + amd_iommu_events_group.attrs = attrs; return 0; } -static __init void amd_iommu_pc_exit(void) -{ - if (__perf_iommu.events_group != NULL) { - kfree(__perf_iommu.events_group); - __perf_iommu.events_group = NULL; - } -} +const struct attribute_group *amd_iommu_attr_groups[] = { + &amd_iommu_format_group, + &amd_iommu_cpumask_group, + &amd_iommu_events_group, + NULL, +}; + +static struct pmu iommu_pmu = { + .event_init = perf_iommu_event_init, + .add = perf_iommu_add, + .del = perf_iommu_del, + .start = perf_iommu_start, + .stop = perf_iommu_stop, + .read = perf_iommu_read, + .task_ctx_nr = perf_invalid_context, + .attr_groups = amd_iommu_attr_groups, +}; -static __init int _init_perf_amd_iommu( - struct perf_amd_iommu *perf_iommu, char *name) +static __init int init_one_iommu(unsigned int idx) { + struct perf_amd_iommu *perf_iommu; int ret; + perf_iommu = kzalloc(sizeof(struct perf_amd_iommu), GFP_KERNEL); + if (!perf_iommu) + return -ENOMEM; + raw_spin_lock_init(&perf_iommu->lock); - /* Init format attributes */ - perf_iommu->format_group = &amd_iommu_format_group; + perf_iommu->pmu = iommu_pmu; + perf_iommu->iommu = get_amd_iommu(idx); + perf_iommu->max_banks = amd_iommu_pc_get_max_banks(idx); + perf_iommu->max_counters = amd_iommu_pc_get_max_counters(idx); - /* Init cpumask attributes to only core 0 */ - cpumask_set_cpu(0, &iommu_cpumask); - perf_iommu->cpumask_group = &amd_iommu_cpumask_group; - - /* Init events attributes */ - if (_init_events_attrs(perf_iommu) != 0) - pr_err("perf: amd_iommu: Only support raw events.\n"); + if (!perf_iommu->iommu || + !perf_iommu->max_banks || + !perf_iommu->max_counters) { + kfree(perf_iommu); + return -EINVAL; + } - /* Init null attributes */ - perf_iommu->null_group = NULL; - perf_iommu->pmu.attr_groups = perf_iommu->attr_groups; + snprintf(perf_iommu->name, IOMMU_NAME_SIZE, "amd_iommu_%u", idx); - ret = perf_pmu_register(&perf_iommu->pmu, name, -1); - if (ret) { - pr_err("perf: amd_iommu: Failed to initialized.\n"); - amd_iommu_pc_exit(); + ret = perf_pmu_register(&perf_iommu->pmu, perf_iommu->name, -1); + if (!ret) { + pr_info("Detected AMD IOMMU #%d (%d banks, %d counters/bank).\n", + idx, perf_iommu->max_banks, perf_iommu->max_counters); + list_add_tail(&perf_iommu->list, &perf_amd_iommu_list); } else { - pr_info("perf: amd_iommu: Detected. (%d banks, %d counters/bank)\n", - amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID), - amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID)); + pr_warn("Error initializing IOMMU %d.\n", idx); + kfree(perf_iommu); } - return ret; } -static struct perf_amd_iommu __perf_iommu = { - .pmu = { - .task_ctx_nr = perf_invalid_context, - .event_init = perf_iommu_event_init, - .add = perf_iommu_add, - .del = perf_iommu_del, - .start = perf_iommu_start, - .stop = perf_iommu_stop, - .read = perf_iommu_read, - }, - .max_banks = 0x00, - .max_counters = 0x00, - .cntr_assign_mask = 0ULL, - .format_group = NULL, - .cpumask_group = NULL, - .events_group = NULL, - .null_group = NULL, -}; - static __init int amd_iommu_pc_init(void) { + unsigned int i, cnt = 0; + int ret; + /* Make sure the IOMMU PC resource is available */ if (!amd_iommu_pc_supported()) return -ENODEV; - _init_perf_amd_iommu(&__perf_iommu, "amd_iommu"); + ret = _init_events_attrs(); + if (ret) + return ret; + + /* + * An IOMMU PMU is specific to an IOMMU, and can function independently. + * So we go through all IOMMUs and ignore the one that fails init + * unless all IOMMU are failing. + */ + for (i = 0; i < amd_iommu_get_num_iommus(); i++) { + ret = init_one_iommu(i); + if (!ret) + cnt++; + } + + if (!cnt) { + kfree(amd_iommu_events_group.attrs); + return -ENODEV; + } + /* Init cpumask attributes to only core 0 */ + cpumask_set_cpu(0, &iommu_cpumask); return 0; } diff --git a/arch/x86/events/amd/iommu.h b/arch/x86/events/amd/iommu.h index 845d173278e3..62e0702c4374 100644 --- a/arch/x86/events/amd/iommu.h +++ b/arch/x86/events/amd/iommu.h @@ -24,17 +24,23 @@ #define PC_MAX_SPEC_BNKS 64 #define PC_MAX_SPEC_CNTRS 16 -/* iommu pc reg masks*/ -#define IOMMU_BASE_DEVID 0x0000 +struct amd_iommu; /* amd_iommu_init.c external support functions */ +extern int amd_iommu_get_num_iommus(void); + extern bool amd_iommu_pc_supported(void); -extern u8 amd_iommu_pc_get_max_banks(u16 devid); +extern u8 amd_iommu_pc_get_max_banks(unsigned int idx); + +extern u8 amd_iommu_pc_get_max_counters(unsigned int idx); + +extern int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value); -extern u8 amd_iommu_pc_get_max_counters(u16 devid); +extern int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value); -extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, - u8 fxn, u64 *value, bool is_write); +extern struct amd_iommu *get_amd_iommu(int idx); #endif /*_PERF_EVENT_AMD_IOMMU_H_*/ diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index 4d1f7f2d9aff..ad44af0dd667 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -30,6 +30,9 @@ #define COUNTER_SHIFT 16 +#undef pr_fmt +#define pr_fmt(fmt) "amd_uncore: " fmt + static int num_counters_llc; static int num_counters_nb; @@ -509,51 +512,34 @@ static int __init amd_uncore_init(void) int ret = -ENODEV; if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) - goto fail_nodev; - - switch(boot_cpu_data.x86) { - case 23: - /* Family 17h: */ - num_counters_nb = NUM_COUNTERS_NB; - num_counters_llc = NUM_COUNTERS_L3; - /* - * For Family17h, the NorthBridge counters are - * re-purposed as Data Fabric counters. Also, support is - * added for L3 counters. The pmus are exported based on - * family as either L2 or L3 and NB or DF. - */ - amd_nb_pmu.name = "amd_df"; - amd_llc_pmu.name = "amd_l3"; - format_attr_event_df.show = &event_show_df; - format_attr_event_l3.show = &event_show_l3; - break; - case 22: - /* Family 16h - may change: */ - num_counters_nb = NUM_COUNTERS_NB; - num_counters_llc = NUM_COUNTERS_L2; - amd_nb_pmu.name = "amd_nb"; - amd_llc_pmu.name = "amd_l2"; - format_attr_event_df = format_attr_event; - format_attr_event_l3 = format_attr_event; - break; - default: - /* - * All prior families have the same number of - * NorthBridge and Last Level Cache counters - */ - num_counters_nb = NUM_COUNTERS_NB; - num_counters_llc = NUM_COUNTERS_L2; - amd_nb_pmu.name = "amd_nb"; - amd_llc_pmu.name = "amd_l2"; - format_attr_event_df = format_attr_event; - format_attr_event_l3 = format_attr_event; - break; - } - amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df; - amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3; + return -ENODEV; if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) - goto fail_nodev; + return -ENODEV; + + if (boot_cpu_data.x86 == 0x17) { + /* + * For F17h, the Northbridge counters are repurposed as Data + * Fabric counters. Also, L3 counters are supported too. The PMUs + * are exported based on family as either L2 or L3 and NB or DF. + */ + num_counters_nb = NUM_COUNTERS_NB; + num_counters_llc = NUM_COUNTERS_L3; + amd_nb_pmu.name = "amd_df"; + amd_llc_pmu.name = "amd_l3"; + format_attr_event_df.show = &event_show_df; + format_attr_event_l3.show = &event_show_l3; + } else { + num_counters_nb = NUM_COUNTERS_NB; + num_counters_llc = NUM_COUNTERS_L2; + amd_nb_pmu.name = "amd_nb"; + amd_llc_pmu.name = "amd_l2"; + format_attr_event_df = format_attr_event; + format_attr_event_l3 = format_attr_event; + } + + amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df; + amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3; if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) { amd_uncore_nb = alloc_percpu(struct amd_uncore *); @@ -565,7 +551,7 @@ static int __init amd_uncore_init(void) if (ret) goto fail_nb; - pr_info("perf: AMD NB counters detected\n"); + pr_info("AMD NB counters detected\n"); ret = 0; } @@ -579,7 +565,7 @@ static int __init amd_uncore_init(void) if (ret) goto fail_llc; - pr_info("perf: AMD LLC counters detected\n"); + pr_info("AMD LLC counters detected\n"); ret = 0; } @@ -615,7 +601,6 @@ fail_nb: if (amd_uncore_nb) free_percpu(amd_uncore_nb); -fail_nodev: return ret; } device_initcall(amd_uncore_init); diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 349d4d17aa7f..580b60f5ac83 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2101,8 +2101,8 @@ static int x86_pmu_event_init(struct perf_event *event) static void refresh_pce(void *ignored) { - if (current->mm) - load_mm_cr4(current->mm); + if (current->active_mm) + load_mm_cr4(current->active_mm); } static void x86_pmu_event_mapped(struct perf_event *event) @@ -2110,6 +2110,18 @@ static void x86_pmu_event_mapped(struct perf_event *event) if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) return; + /* + * This function relies on not being called concurrently in two + * tasks in the same mm. Otherwise one task could observe + * perf_rdpmc_allowed > 1 and return all the way back to + * userspace with CR4.PCE clear while another task is still + * doing on_each_cpu_mask() to propagate CR4.PCE. + * + * For now, this can't happen because all callers hold mmap_sem + * for write. If this changes, we'll need a different solution. + */ + lockdep_assert_held_exclusive(¤t->mm->mmap_sem); + if (atomic_inc_return(¤t->mm->context.perf_rdpmc_allowed) == 1) on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); } @@ -2244,6 +2256,7 @@ void arch_perf_update_userpage(struct perf_event *event, struct perf_event_mmap_page *userpg, u64 now) { struct cyc2ns_data *data; + u64 offset; userpg->cap_user_time = 0; userpg->cap_user_time_zero = 0; @@ -2251,11 +2264,13 @@ void arch_perf_update_userpage(struct perf_event *event, !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED); userpg->pmc_width = x86_pmu.cntval_bits; - if (!sched_clock_stable()) + if (!using_native_sched_clock() || !sched_clock_stable()) return; data = cyc2ns_read_begin(); + offset = data->cyc2ns_offset + __sched_clock_offset; + /* * Internal timekeeping for enabled/running/stopped times * is always in the local_clock domain. @@ -2263,7 +2278,7 @@ void arch_perf_update_userpage(struct perf_event *event, userpg->cap_user_time = 1; userpg->time_mult = data->cyc2ns_mul; userpg->time_shift = data->cyc2ns_shift; - userpg->time_offset = data->cyc2ns_offset - now; + userpg->time_offset = offset - now; /* * cap_user_time_zero doesn't make sense when we're using a different @@ -2271,7 +2286,7 @@ void arch_perf_update_userpage(struct perf_event *event, */ if (!event->attr.use_clockid) { userpg->cap_user_time_zero = 1; - userpg->time_zero = data->cyc2ns_offset; + userpg->time_zero = offset; } cyc2ns_read_end(data); diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c index 982c9e31daca..8ae8c5ce3a1f 100644 --- a/arch/x86/events/intel/bts.c +++ b/arch/x86/events/intel/bts.c @@ -63,7 +63,6 @@ struct bts_buffer { unsigned int cur_buf; bool snapshot; local_t data_size; - local_t lost; local_t head; unsigned long end; void **data_pages; @@ -199,7 +198,8 @@ static void bts_update(struct bts_ctx *bts) return; if (ds->bts_index >= ds->bts_absolute_maximum) - local_inc(&buf->lost); + perf_aux_output_flag(&bts->handle, + PERF_AUX_FLAG_TRUNCATED); /* * old and head are always in the same physical buffer, so we @@ -276,7 +276,7 @@ static void bts_event_start(struct perf_event *event, int flags) return; fail_end_stop: - perf_aux_output_end(&bts->handle, 0, false); + perf_aux_output_end(&bts->handle, 0); fail_stop: event->hw.state = PERF_HES_STOPPED; @@ -319,9 +319,8 @@ static void bts_event_stop(struct perf_event *event, int flags) bts->handle.head = local_xchg(&buf->data_size, buf->nr_pages << PAGE_SHIFT); - - perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), - !!local_xchg(&buf->lost, 0)); + perf_aux_output_end(&bts->handle, + local_xchg(&buf->data_size, 0)); } cpuc->ds->bts_index = bts->ds_back.bts_buffer_base; @@ -484,8 +483,7 @@ int intel_bts_interrupt(void) if (old_head == local_read(&buf->head)) return handled; - perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), - !!local_xchg(&buf->lost, 0)); + perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0)); buf = perf_aux_output_begin(&bts->handle, event); if (buf) @@ -500,7 +498,7 @@ int intel_bts_interrupt(void) * cleared handle::event */ barrier(); - perf_aux_output_end(&bts->handle, 0, false); + perf_aux_output_end(&bts->handle, 0); } } diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index eb1484c86bb4..a6d91d4e37a1 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -1553,6 +1553,27 @@ static __initconst const u64 slm_hw_cache_event_ids }, }; +EVENT_ATTR_STR(topdown-total-slots, td_total_slots_glm, "event=0x3c"); +EVENT_ATTR_STR(topdown-total-slots.scale, td_total_slots_scale_glm, "3"); +/* UOPS_NOT_DELIVERED.ANY */ +EVENT_ATTR_STR(topdown-fetch-bubbles, td_fetch_bubbles_glm, "event=0x9c"); +/* ISSUE_SLOTS_NOT_CONSUMED.RECOVERY */ +EVENT_ATTR_STR(topdown-recovery-bubbles, td_recovery_bubbles_glm, "event=0xca,umask=0x02"); +/* UOPS_RETIRED.ANY */ +EVENT_ATTR_STR(topdown-slots-retired, td_slots_retired_glm, "event=0xc2"); +/* UOPS_ISSUED.ANY */ +EVENT_ATTR_STR(topdown-slots-issued, td_slots_issued_glm, "event=0x0e"); + +static struct attribute *glm_events_attrs[] = { + EVENT_PTR(td_total_slots_glm), + EVENT_PTR(td_total_slots_scale_glm), + EVENT_PTR(td_fetch_bubbles_glm), + EVENT_PTR(td_recovery_bubbles_glm), + EVENT_PTR(td_slots_issued_glm), + EVENT_PTR(td_slots_retired_glm), + NULL +}; + static struct extra_reg intel_glm_extra_regs[] __read_mostly = { /* must define OFFCORE_RSP_X first, see intel_fixup_er() */ INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0), @@ -2130,7 +2151,7 @@ again: * counters from the GLOBAL_STATUS mask and we always process PEBS * events via drain_pebs(). */ - status &= ~cpuc->pebs_enabled; + status &= ~(cpuc->pebs_enabled & PEBS_COUNTER_MASK); /* * PEBS overflow sets bit 62 in the global status register @@ -3750,6 +3771,7 @@ __init int intel_pmu_init(void) x86_pmu.pebs_prec_dist = true; x86_pmu.lbr_pt_coexist = true; x86_pmu.flags |= PMU_FL_HAS_RSP_1; + x86_pmu.cpu_events = glm_events_attrs; pr_cont("Goldmont events, "); break; diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index aff4b5b69d40..238ae3248ba5 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -1,5 +1,5 @@ /* - * perf_event_intel_cstate.c: support cstate residency counters + * Support cstate residency counters * * Copyright (C) 2015, Intel Corp. * Author: Kan Liang (kan.liang@intel.com) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 9dfeeeca0ea8..c6d23ffe422d 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1222,7 +1222,7 @@ get_next_pebs_record_by_bit(void *base, void *top, int bit) /* clear non-PEBS bit and re-check */ pebs_status = p->status & cpuc->pebs_enabled; - pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1; + pebs_status &= PEBS_COUNTER_MASK; if (pebs_status == (1 << bit)) return at; } diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 81b321ace8e0..f924629836a8 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -507,6 +507,9 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) cpuc->lbr_entries[i].to = msr_lastbranch.to; cpuc->lbr_entries[i].mispred = 0; cpuc->lbr_entries[i].predicted = 0; + cpuc->lbr_entries[i].in_tx = 0; + cpuc->lbr_entries[i].abort = 0; + cpuc->lbr_entries[i].cycles = 0; cpuc->lbr_entries[i].reserved = 0; } cpuc->lbr_stack.nr = i; diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index 5900471ee508..ae8324d65e61 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -28,6 +28,7 @@ #include <asm/insn.h> #include <asm/io.h> #include <asm/intel_pt.h> +#include <asm/intel-family.h> #include "../perf_event.h" #include "pt.h" @@ -98,6 +99,7 @@ static struct attribute_group pt_cap_group = { .name = "caps", }; +PMU_FORMAT_ATTR(pt, "config:0" ); PMU_FORMAT_ATTR(cyc, "config:1" ); PMU_FORMAT_ATTR(pwr_evt, "config:4" ); PMU_FORMAT_ATTR(fup_on_ptw, "config:5" ); @@ -105,11 +107,13 @@ PMU_FORMAT_ATTR(mtc, "config:9" ); PMU_FORMAT_ATTR(tsc, "config:10" ); PMU_FORMAT_ATTR(noretcomp, "config:11" ); PMU_FORMAT_ATTR(ptw, "config:12" ); +PMU_FORMAT_ATTR(branch, "config:13" ); PMU_FORMAT_ATTR(mtc_period, "config:14-17" ); PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" ); PMU_FORMAT_ATTR(psb_period, "config:24-27" ); static struct attribute *pt_formats_attr[] = { + &format_attr_pt.attr, &format_attr_cyc.attr, &format_attr_pwr_evt.attr, &format_attr_fup_on_ptw.attr, @@ -117,6 +121,7 @@ static struct attribute *pt_formats_attr[] = { &format_attr_tsc.attr, &format_attr_noretcomp.attr, &format_attr_ptw.attr, + &format_attr_branch.attr, &format_attr_mtc_period.attr, &format_attr_cyc_thresh.attr, &format_attr_psb_period.attr, @@ -197,6 +202,19 @@ static int __init pt_pmu_hw_init(void) pt_pmu.tsc_art_den = eax; } + /* model-specific quirks */ + switch (boot_cpu_data.x86_model) { + case INTEL_FAM6_BROADWELL_CORE: + case INTEL_FAM6_BROADWELL_XEON_D: + case INTEL_FAM6_BROADWELL_GT3E: + case INTEL_FAM6_BROADWELL_X: + /* not setting BRANCH_EN will #GP, erratum BDM106 */ + pt_pmu.branch_en_always_on = true; + break; + default: + break; + } + if (boot_cpu_has(X86_FEATURE_VMX)) { /* * Intel SDM, 36.5 "Tracing post-VMXON" says that @@ -263,8 +281,20 @@ fail: #define RTIT_CTL_PTW (RTIT_CTL_PTW_EN | \ RTIT_CTL_FUP_ON_PTW) -#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | \ +/* + * Bit 0 (TraceEn) in the attr.config is meaningless as the + * corresponding bit in the RTIT_CTL can only be controlled + * by the driver; therefore, repurpose it to mean: pass + * through the bit that was previously assumed to be always + * on for PT, thereby allowing the user to *not* set it if + * they so wish. See also pt_event_valid() and pt_config(). + */ +#define RTIT_CTL_PASSTHROUGH RTIT_CTL_TRACEEN + +#define PT_CONFIG_MASK (RTIT_CTL_TRACEEN | \ + RTIT_CTL_TSC_EN | \ RTIT_CTL_DISRETC | \ + RTIT_CTL_BRANCH_EN | \ RTIT_CTL_CYC_PSB | \ RTIT_CTL_MTC | \ RTIT_CTL_PWR_EVT_EN | \ @@ -332,6 +362,33 @@ static bool pt_event_valid(struct perf_event *event) return false; } + /* + * Setting bit 0 (TraceEn in RTIT_CTL MSR) in the attr.config + * clears the assomption that BranchEn must always be enabled, + * as was the case with the first implementation of PT. + * If this bit is not set, the legacy behavior is preserved + * for compatibility with the older userspace. + * + * Re-using bit 0 for this purpose is fine because it is never + * directly set by the user; previous attempts at setting it in + * the attr.config resulted in -EINVAL. + */ + if (config & RTIT_CTL_PASSTHROUGH) { + /* + * Disallow not setting BRANCH_EN where BRANCH_EN is + * always required. + */ + if (pt_pmu.branch_en_always_on && + !(config & RTIT_CTL_BRANCH_EN)) + return false; + } else { + /* + * Disallow BRANCH_EN without the PASSTHROUGH. + */ + if (config & RTIT_CTL_BRANCH_EN) + return false; + } + return true; } @@ -411,6 +468,7 @@ static u64 pt_config_filters(struct perf_event *event) static void pt_config(struct perf_event *event) { + struct pt *pt = this_cpu_ptr(&pt_ctx); u64 reg; if (!event->hw.itrace_started) { @@ -419,7 +477,20 @@ static void pt_config(struct perf_event *event) } reg = pt_config_filters(event); - reg |= RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN; + reg |= RTIT_CTL_TOPA | RTIT_CTL_TRACEEN; + + /* + * Previously, we had BRANCH_EN on by default, but now that PT has + * grown features outside of branch tracing, it is useful to allow + * the user to disable it. Setting bit 0 in the event's attr.config + * allows BRANCH_EN to pass through instead of being always on. See + * also the comment in pt_event_valid(). + */ + if (event->attr.config & BIT(0)) { + reg |= event->attr.config & RTIT_CTL_BRANCH_EN; + } else { + reg |= RTIT_CTL_BRANCH_EN; + } if (!event->attr.exclude_kernel) reg |= RTIT_CTL_OS; @@ -429,11 +500,15 @@ static void pt_config(struct perf_event *event) reg |= (event->attr.config & PT_CONFIG_MASK); event->hw.config = reg; - wrmsrl(MSR_IA32_RTIT_CTL, reg); + if (READ_ONCE(pt->vmx_on)) + perf_aux_output_flag(&pt->handle, PERF_AUX_FLAG_PARTIAL); + else + wrmsrl(MSR_IA32_RTIT_CTL, reg); } static void pt_config_stop(struct perf_event *event) { + struct pt *pt = this_cpu_ptr(&pt_ctx); u64 ctl = READ_ONCE(event->hw.config); /* may be already stopped by a PMI */ @@ -441,7 +516,8 @@ static void pt_config_stop(struct perf_event *event) return; ctl &= ~RTIT_CTL_TRACEEN; - wrmsrl(MSR_IA32_RTIT_CTL, ctl); + if (!READ_ONCE(pt->vmx_on)) + wrmsrl(MSR_IA32_RTIT_CTL, ctl); WRITE_ONCE(event->hw.config, ctl); @@ -753,7 +829,8 @@ static void pt_handle_status(struct pt *pt) */ if (!pt_cap_get(PT_CAP_topa_multiple_entries) || buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) { - local_inc(&buf->lost); + perf_aux_output_flag(&pt->handle, + PERF_AUX_FLAG_TRUNCATED); advance++; } } @@ -846,8 +923,10 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf, /* can't stop in the middle of an output region */ if (buf->output_off + handle->size + 1 < - sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) + sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) { + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); return -EINVAL; + } /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */ @@ -1171,12 +1250,6 @@ void intel_pt_interrupt(void) if (!READ_ONCE(pt->handle_nmi)) return; - /* - * If VMX is on and PT does not support it, don't touch anything. - */ - if (READ_ONCE(pt->vmx_on)) - return; - if (!event) return; @@ -1192,8 +1265,7 @@ void intel_pt_interrupt(void) pt_update_head(pt); - perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0), - local_xchg(&buf->lost, 0)); + perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0)); if (!event->hw.state) { int ret; @@ -1208,7 +1280,7 @@ void intel_pt_interrupt(void) /* snapshot counters don't use PMI, so it's safe */ ret = pt_buffer_reset_markers(buf, &pt->handle); if (ret) { - perf_aux_output_end(&pt->handle, 0, true); + perf_aux_output_end(&pt->handle, 0); return; } @@ -1237,12 +1309,19 @@ void intel_pt_handle_vmx(int on) local_irq_save(flags); WRITE_ONCE(pt->vmx_on, on); - if (on) { - /* prevent pt_config_stop() from writing RTIT_CTL */ - event = pt->handle.event; - if (event) - event->hw.config = 0; - } + /* + * If an AUX transaction is in progress, it will contain + * gap(s), so flag it PARTIAL to inform the user. + */ + event = pt->handle.event; + if (event) + perf_aux_output_flag(&pt->handle, + PERF_AUX_FLAG_PARTIAL); + + /* Turn PTs back on */ + if (!on && event) + wrmsrl(MSR_IA32_RTIT_CTL, event->hw.config); + local_irq_restore(flags); } EXPORT_SYMBOL_GPL(intel_pt_handle_vmx); @@ -1257,9 +1336,6 @@ static void pt_event_start(struct perf_event *event, int mode) struct pt *pt = this_cpu_ptr(&pt_ctx); struct pt_buffer *buf; - if (READ_ONCE(pt->vmx_on)) - return; - buf = perf_aux_output_begin(&pt->handle, event); if (!buf) goto fail_stop; @@ -1280,7 +1356,7 @@ static void pt_event_start(struct perf_event *event, int mode) return; fail_end_stop: - perf_aux_output_end(&pt->handle, 0, true); + perf_aux_output_end(&pt->handle, 0); fail_stop: hwc->state = PERF_HES_STOPPED; } @@ -1321,8 +1397,7 @@ static void pt_event_stop(struct perf_event *event, int mode) pt->handle.head = local_xchg(&buf->data_size, buf->nr_pages << PAGE_SHIFT); - perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0), - local_xchg(&buf->lost, 0)); + perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0)); } } diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h index 53473c21b554..0eb41d07b79a 100644 --- a/arch/x86/events/intel/pt.h +++ b/arch/x86/events/intel/pt.h @@ -110,6 +110,7 @@ struct pt_pmu { struct pmu pmu; u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES]; bool vmx; + bool branch_en_always_on; unsigned long max_nonturbo_ratio; unsigned int tsc_art_num; unsigned int tsc_art_den; @@ -143,7 +144,6 @@ struct pt_buffer { size_t output_off; unsigned long nr_pages; local_t data_size; - local_t lost; local64_t head; bool snapshot; unsigned long stop_pos, intr_pos; diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 22054ca49026..9d05c7e67f60 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -1,5 +1,5 @@ /* - * perf_event_intel_rapl.c: support Intel RAPL energy consumption counters + * Support Intel RAPL energy consumption counters * Copyright (C) 2013 Google, Inc., Stephane Eranian * * Intel RAPL interface is specified in the IA-32 Manual Vol3b diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h index ad986c1e29bc..df5989f27b1b 100644 --- a/arch/x86/events/intel/uncore.h +++ b/arch/x86/events/intel/uncore.h @@ -360,7 +360,7 @@ extern struct list_head pci2phy_map_head; extern struct pci_extra_dev *uncore_extra_pci_dev; extern struct event_constraint uncore_constraint_empty; -/* perf_event_intel_uncore_snb.c */ +/* uncore_snb.c */ int snb_uncore_pci_init(void); int ivb_uncore_pci_init(void); int hsw_uncore_pci_init(void); @@ -371,7 +371,7 @@ void nhm_uncore_cpu_init(void); void skl_uncore_cpu_init(void); int snb_pci2phy_map_init(int devid); -/* perf_event_intel_uncore_snbep.c */ +/* uncore_snbep.c */ int snbep_uncore_pci_init(void); void snbep_uncore_cpu_init(void); int ivbep_uncore_pci_init(void); @@ -385,5 +385,5 @@ void knl_uncore_cpu_init(void); int skx_uncore_pci_init(void); void skx_uncore_cpu_init(void); -/* perf_event_intel_uncore_nhmex.c */ +/* uncore_nhmex.c */ void nhmex_uncore_cpu_init(void); diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index bcbb1d2ae10b..be3d36254040 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -79,6 +79,7 @@ struct amd_nb { /* The maximal number of PEBS events: */ #define MAX_PEBS_EVENTS 8 +#define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1) /* * Flags PEBS can handle without an PMI. diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index db64baf0e500..2b01421f7d0f 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -27,45 +27,22 @@ #include <linux/clockchips.h> -#ifdef CONFIG_X86_64 +#ifdef CONFIG_HYPERV_TSCPAGE static struct ms_hyperv_tsc_page *tsc_pg; +struct ms_hyperv_tsc_page *hv_get_tsc_page(void) +{ + return tsc_pg; +} + static u64 read_hv_clock_tsc(struct clocksource *arg) { - u64 current_tick; + u64 current_tick = hv_read_tsc_page(tsc_pg); + + if (current_tick == U64_MAX) + rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick); - if (tsc_pg->tsc_sequence != 0) { - /* - * Use the tsc page to compute the value. - */ - - while (1) { - u64 tmp; - u32 sequence = tsc_pg->tsc_sequence; - u64 cur_tsc; - u64 scale = tsc_pg->tsc_scale; - s64 offset = tsc_pg->tsc_offset; - - rdtscll(cur_tsc); - /* current_tick = ((cur_tsc *scale) >> 64) + offset */ - asm("mulq %3" - : "=d" (current_tick), "=a" (tmp) - : "a" (cur_tsc), "r" (scale)); - - current_tick += offset; - if (tsc_pg->tsc_sequence == sequence) - return current_tick; - - if (tsc_pg->tsc_sequence != 0) - continue; - /* - * Fallback using MSR method. - */ - break; - } - } - rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick); return current_tick; } @@ -139,7 +116,7 @@ void hyperv_init(void) /* * Register Hyper-V specific clocksource. */ -#ifdef CONFIG_X86_64 +#ifdef CONFIG_HYPERV_TSCPAGE if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { union hv_x64_msr_hypercall_contents tsc_msr; @@ -155,16 +132,19 @@ void hyperv_init(void) tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg); wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64); + + hyperv_cs_tsc.archdata.vclock_mode = VCLOCK_HVCLOCK; + clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); return; } +register_msr_cs: #endif /* * For 32 bit guests just use the MSR based mechanism for reading * the partition counter. */ -register_msr_cs: hyperv_cs = &hyperv_cs_msr; if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 395b69551fce..2efc768e4362 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -52,6 +52,8 @@ extern u8 acpi_sci_flags; extern int acpi_sci_override_gsi; void acpi_pic_sci_set_trigger(unsigned int, u16); +struct device; + extern int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity); extern void (*__acpi_unregister_gsi)(u32 gsi); diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 730ef65e8393..bdffcd9eab2b 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -252,12 +252,6 @@ static inline int x2apic_enabled(void) { return 0; } #define x2apic_supported() (0) #endif /* !CONFIG_X86_X2APIC */ -#ifdef CONFIG_X86_64 -#define SET_APIC_ID(x) (apic->set_apic_id(x)) -#else - -#endif - /* * Copyright 2004 James Cleverdon, IBM. * Subject to the GNU Public License, v.2 @@ -299,6 +293,7 @@ struct apic { int (*phys_pkg_id)(int cpuid_apic, int index_msb); unsigned int (*get_apic_id)(unsigned long x); + /* Can't be NULL on 64-bit */ unsigned long (*set_apic_id)(unsigned int id); int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 14635c5ea025..caa5798c92f4 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -186,6 +186,12 @@ static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new) return cmpxchg(&v->counter, old, new); } +#define atomic_try_cmpxchg atomic_try_cmpxchg +static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new) +{ + return try_cmpxchg(&v->counter, old, new); +} + static inline int atomic_xchg(atomic_t *v, int new) { return xchg(&v->counter, new); @@ -201,16 +207,12 @@ static inline void atomic_##op(int i, atomic_t *v) \ } #define ATOMIC_FETCH_OP(op, c_op) \ -static inline int atomic_fetch_##op(int i, atomic_t *v) \ +static inline int atomic_fetch_##op(int i, atomic_t *v) \ { \ - int old, val = atomic_read(v); \ - for (;;) { \ - old = atomic_cmpxchg(v, val, val c_op i); \ - if (old == val) \ - break; \ - val = old; \ - } \ - return old; \ + int val = atomic_read(v); \ + do { \ + } while (!atomic_try_cmpxchg(v, &val, val c_op i)); \ + return val; \ } #define ATOMIC_OPS(op, c_op) \ @@ -236,16 +238,11 @@ ATOMIC_OPS(xor, ^) */ static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u) { - int c, old; - c = atomic_read(v); - for (;;) { - if (unlikely(c == (u))) - break; - old = atomic_cmpxchg((v), c, c + (a)); - if (likely(old == c)) + int c = atomic_read(v); + do { + if (unlikely(c == u)) break; - c = old; - } + } while (!atomic_try_cmpxchg(v, &c, c + a)); return c; } diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 89ed2f6ae2f7..6189a433c9a9 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h @@ -176,6 +176,12 @@ static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) return cmpxchg(&v->counter, old, new); } +#define atomic64_try_cmpxchg atomic64_try_cmpxchg +static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, long *old, long new) +{ + return try_cmpxchg(&v->counter, old, new); +} + static inline long atomic64_xchg(atomic64_t *v, long new) { return xchg(&v->counter, new); @@ -192,17 +198,12 @@ static inline long atomic64_xchg(atomic64_t *v, long new) */ static inline bool atomic64_add_unless(atomic64_t *v, long a, long u) { - long c, old; - c = atomic64_read(v); - for (;;) { - if (unlikely(c == (u))) - break; - old = atomic64_cmpxchg((v), c, c + (a)); - if (likely(old == c)) - break; - c = old; - } - return c != (u); + long c = atomic64_read(v); + do { + if (unlikely(c == u)) + return false; + } while (!atomic64_try_cmpxchg(v, &c, c + a)); + return true; } #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) @@ -216,17 +217,12 @@ static inline bool atomic64_add_unless(atomic64_t *v, long a, long u) */ static inline long atomic64_dec_if_positive(atomic64_t *v) { - long c, old, dec; - c = atomic64_read(v); - for (;;) { + long dec, c = atomic64_read(v); + do { dec = c - 1; if (unlikely(dec < 0)) break; - old = atomic64_cmpxchg((v), c, dec); - if (likely(old == c)) - break; - c = old; - } + } while (!atomic64_try_cmpxchg(v, &c, dec)); return dec; } @@ -242,14 +238,10 @@ static inline void atomic64_##op(long i, atomic64_t *v) \ #define ATOMIC64_FETCH_OP(op, c_op) \ static inline long atomic64_fetch_##op(long i, atomic64_t *v) \ { \ - long old, val = atomic64_read(v); \ - for (;;) { \ - old = atomic64_cmpxchg(v, val, val c_op i); \ - if (old == val) \ - break; \ - val = old; \ - } \ - return old; \ + long val = atomic64_read(v); \ + do { \ + } while (!atomic64_try_cmpxchg(v, &val, val c_op i)); \ + return val; \ } #define ATOMIC64_OPS(op, c_op) \ diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index ba38ebbaced3..39e702d90cdb 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -1,36 +1,82 @@ #ifndef _ASM_X86_BUG_H #define _ASM_X86_BUG_H -#define HAVE_ARCH_BUG +#include <linux/stringify.h> -#ifdef CONFIG_DEBUG_BUGVERBOSE +/* + * Since some emulators terminate on UD2, we cannot use it for WARN. + * Since various instruction decoders disagree on the length of UD1, + * we cannot use it either. So use UD0 for WARN. + * + * (binutils knows about "ud1" but {en,de}codes it as 2 bytes, whereas + * our kernel decoder thinks it takes a ModRM byte, which seems consistent + * with various things like the Intel SDM instruction encoding rules) + */ + +#define ASM_UD0 ".byte 0x0f, 0xff" +#define ASM_UD1 ".byte 0x0f, 0xb9" /* + ModRM */ +#define ASM_UD2 ".byte 0x0f, 0x0b" + +#define INSN_UD0 0xff0f +#define INSN_UD2 0x0b0f + +#define LEN_UD0 2 + +#ifdef CONFIG_GENERIC_BUG #ifdef CONFIG_X86_32 -# define __BUG_C0 "2:\t.long 1b, %c0\n" +# define __BUG_REL(val) ".long " __stringify(val) #else -# define __BUG_C0 "2:\t.long 1b - 2b, %c0 - 2b\n" +# define __BUG_REL(val) ".long " __stringify(val) " - 2b" #endif -#define BUG() \ -do { \ - asm volatile("1:\tud2\n" \ - ".pushsection __bug_table,\"a\"\n" \ - __BUG_C0 \ - "\t.word %c1, 0\n" \ - "\t.org 2b+%c2\n" \ - ".popsection" \ - : : "i" (__FILE__), "i" (__LINE__), \ - "i" (sizeof(struct bug_entry))); \ - unreachable(); \ +#ifdef CONFIG_DEBUG_BUGVERBOSE + +#define _BUG_FLAGS(ins, flags) \ +do { \ + asm volatile("1:\t" ins "\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ + "\t" __BUG_REL(%c0) "\t# bug_entry::file\n" \ + "\t.word %c1" "\t# bug_entry::line\n" \ + "\t.word %c2" "\t# bug_entry::flags\n" \ + "\t.org 2b+%c3\n" \ + ".popsection" \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (flags), \ + "i" (sizeof(struct bug_entry))); \ } while (0) +#else /* !CONFIG_DEBUG_BUGVERBOSE */ + +#define _BUG_FLAGS(ins, flags) \ +do { \ + asm volatile("1:\t" ins "\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ + "\t.word %c0" "\t# bug_entry::flags\n" \ + "\t.org 2b+%c1\n" \ + ".popsection" \ + : : "i" (flags), \ + "i" (sizeof(struct bug_entry))); \ +} while (0) + +#endif /* CONFIG_DEBUG_BUGVERBOSE */ + #else + +#define _BUG_FLAGS(ins, flags) asm volatile(ins) + +#endif /* CONFIG_GENERIC_BUG */ + +#define HAVE_ARCH_BUG #define BUG() \ do { \ - asm volatile("ud2"); \ + _BUG_FLAGS(ASM_UD2, 0); \ unreachable(); \ } while (0) -#endif + +#define __WARN_FLAGS(flags) _BUG_FLAGS(ASM_UD0, BUGFLAG_WARNING|(flags)) #include <asm-generic/bug.h> diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h index eae33c7170c8..47bea8cadbd0 100644 --- a/arch/x86/include/asm/clocksource.h +++ b/arch/x86/include/asm/clocksource.h @@ -6,7 +6,8 @@ #define VCLOCK_NONE 0 /* No vDSO clock available. */ #define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ #define VCLOCK_PVCLOCK 2 /* vDSO should use vread_pvclock. */ -#define VCLOCK_MAX 2 +#define VCLOCK_HVCLOCK 3 /* vDSO should use vread_hvclock. */ +#define VCLOCK_MAX 3 struct arch_clocksource_data { int vclock_mode; diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index 97848cdfcb1a..d90296d061e8 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -153,6 +153,76 @@ extern void __add_wrong_size(void) #define cmpxchg_local(ptr, old, new) \ __cmpxchg_local(ptr, old, new, sizeof(*(ptr))) + +#define __raw_try_cmpxchg(_ptr, _pold, _new, size, lock) \ +({ \ + bool success; \ + __typeof__(_ptr) _old = (_pold); \ + __typeof__(*(_ptr)) __old = *_old; \ + __typeof__(*(_ptr)) __new = (_new); \ + switch (size) { \ + case __X86_CASE_B: \ + { \ + volatile u8 *__ptr = (volatile u8 *)(_ptr); \ + asm volatile(lock "cmpxchgb %[new], %[ptr]" \ + CC_SET(z) \ + : CC_OUT(z) (success), \ + [ptr] "+m" (*__ptr), \ + [old] "+a" (__old) \ + : [new] "q" (__new) \ + : "memory"); \ + break; \ + } \ + case __X86_CASE_W: \ + { \ + volatile u16 *__ptr = (volatile u16 *)(_ptr); \ + asm volatile(lock "cmpxchgw %[new], %[ptr]" \ + CC_SET(z) \ + : CC_OUT(z) (success), \ + [ptr] "+m" (*__ptr), \ + [old] "+a" (__old) \ + : [new] "r" (__new) \ + : "memory"); \ + break; \ + } \ + case __X86_CASE_L: \ + { \ + volatile u32 *__ptr = (volatile u32 *)(_ptr); \ + asm volatile(lock "cmpxchgl %[new], %[ptr]" \ + CC_SET(z) \ + : CC_OUT(z) (success), \ + [ptr] "+m" (*__ptr), \ + [old] "+a" (__old) \ + : [new] "r" (__new) \ + : "memory"); \ + break; \ + } \ + case __X86_CASE_Q: \ + { \ + volatile u64 *__ptr = (volatile u64 *)(_ptr); \ + asm volatile(lock "cmpxchgq %[new], %[ptr]" \ + CC_SET(z) \ + : CC_OUT(z) (success), \ + [ptr] "+m" (*__ptr), \ + [old] "+a" (__old) \ + : [new] "r" (__new) \ + : "memory"); \ + break; \ + } \ + default: \ + __cmpxchg_wrong_size(); \ + } \ + if (unlikely(!success)) \ + *_old = __old; \ + likely(success); \ +}) + +#define __try_cmpxchg(ptr, pold, new, size) \ + __raw_try_cmpxchg((ptr), (pold), (new), (size), LOCK_PREFIX) + +#define try_cmpxchg(ptr, pold, new) \ + __try_cmpxchg((ptr), (pold), (new), sizeof(*(ptr))) + /* * xadd() adds "inc" to "*ptr" and atomically returns the previous * value of "*ptr". diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 4e7772387c6e..2701e5f8145b 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -187,6 +187,7 @@ * Reuse free bits when adding new feature flags! */ #define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */ +#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */ #define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ #define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ #define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ @@ -201,6 +202,8 @@ #define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */ #define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */ +#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ + /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ #define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ @@ -289,7 +292,8 @@ #define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ #define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ #define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ -#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */ +#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ +#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */ #define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */ diff --git a/arch/x86/include/asm/crypto/glue_helper.h b/arch/x86/include/asm/crypto/glue_helper.h index 29e53ea7d764..ed8b66de541f 100644 --- a/arch/x86/include/asm/crypto/glue_helper.h +++ b/arch/x86/include/asm/crypto/glue_helper.h @@ -125,16 +125,6 @@ static inline void le128_inc(le128 *i) i->b = cpu_to_le64(b); } -static inline void le128_gf128mul_x_ble(le128 *dst, const le128 *src) -{ - u64 a = le64_to_cpu(src->a); - u64 b = le64_to_cpu(src->b); - u64 _tt = ((s64)a >> 63) & 0x87; - - dst->a = cpu_to_le64((a << 1) ^ (b >> 63)); - dst->b = cpu_to_le64((b << 1) ^ _tt); -} - extern int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, struct blkcipher_desc *desc, struct scatterlist *dst, diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index 1548ca92ad3f..d0a21b12dd58 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h @@ -4,6 +4,7 @@ #include <asm/desc_defs.h> #include <asm/ldt.h> #include <asm/mmu.h> +#include <asm/fixmap.h> #include <linux/smp.h> #include <linux/percpu.h> @@ -45,11 +46,43 @@ struct gdt_page { DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page); -static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) +/* Provide the original GDT */ +static inline struct desc_struct *get_cpu_gdt_rw(unsigned int cpu) { return per_cpu(gdt_page, cpu).gdt; } +/* Provide the current original GDT */ +static inline struct desc_struct *get_current_gdt_rw(void) +{ + return this_cpu_ptr(&gdt_page)->gdt; +} + +/* Get the fixmap index for a specific processor */ +static inline unsigned int get_cpu_gdt_ro_index(int cpu) +{ + return FIX_GDT_REMAP_BEGIN + cpu; +} + +/* Provide the fixmap address of the remapped GDT */ +static inline struct desc_struct *get_cpu_gdt_ro(int cpu) +{ + unsigned int idx = get_cpu_gdt_ro_index(cpu); + return (struct desc_struct *)__fix_to_virt(idx); +} + +/* Provide the current read-only GDT */ +static inline struct desc_struct *get_current_gdt_ro(void) +{ + return get_cpu_gdt_ro(smp_processor_id()); +} + +/* Provide the physical address of the GDT page. */ +static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu) +{ + return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu)); +} + #ifdef CONFIG_X86_64 static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, @@ -174,7 +207,7 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned t static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr) { - struct desc_struct *d = get_cpu_gdt_table(cpu); + struct desc_struct *d = get_cpu_gdt_rw(cpu); tss_desc tss; set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS, @@ -194,22 +227,90 @@ static inline void native_set_ldt(const void *addr, unsigned int entries) set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT, entries * LDT_ENTRY_SIZE - 1); - write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, + write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_LDT, &ldt, DESC_LDT); asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8)); } } +static inline void native_load_gdt(const struct desc_ptr *dtr) +{ + asm volatile("lgdt %0"::"m" (*dtr)); +} + +static inline void native_load_idt(const struct desc_ptr *dtr) +{ + asm volatile("lidt %0"::"m" (*dtr)); +} + +static inline void native_store_gdt(struct desc_ptr *dtr) +{ + asm volatile("sgdt %0":"=m" (*dtr)); +} + +static inline void native_store_idt(struct desc_ptr *dtr) +{ + asm volatile("sidt %0":"=m" (*dtr)); +} + +/* + * The LTR instruction marks the TSS GDT entry as busy. On 64-bit, the GDT is + * a read-only remapping. To prevent a page fault, the GDT is switched to the + * original writeable version when needed. + */ +#ifdef CONFIG_X86_64 +static inline void native_load_tr_desc(void) +{ + struct desc_ptr gdt; + int cpu = raw_smp_processor_id(); + bool restore = 0; + struct desc_struct *fixmap_gdt; + + native_store_gdt(&gdt); + fixmap_gdt = get_cpu_gdt_ro(cpu); + + /* + * If the current GDT is the read-only fixmap, swap to the original + * writeable version. Swap back at the end. + */ + if (gdt.address == (unsigned long)fixmap_gdt) { + load_direct_gdt(cpu); + restore = 1; + } + asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); + if (restore) + load_fixmap_gdt(cpu); +} +#else static inline void native_load_tr_desc(void) { asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); } +#endif + +static inline unsigned long native_store_tr(void) +{ + unsigned long tr; + + asm volatile("str %0":"=r" (tr)); + + return tr; +} + +static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) +{ + struct desc_struct *gdt = get_cpu_gdt_rw(cpu); + unsigned int i; + + for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) + gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; +} DECLARE_PER_CPU(bool, __tss_limit_invalid); static inline void force_reload_TR(void) { - struct desc_struct *d = get_cpu_gdt_table(smp_processor_id()); + struct desc_struct *d = get_current_gdt_rw(); tss_desc tss; memcpy(&tss, &d[GDT_ENTRY_TSS], sizeof(tss_desc)); @@ -257,44 +358,6 @@ static inline void invalidate_tss_limit(void) this_cpu_write(__tss_limit_invalid, true); } -static inline void native_load_gdt(const struct desc_ptr *dtr) -{ - asm volatile("lgdt %0"::"m" (*dtr)); -} - -static inline void native_load_idt(const struct desc_ptr *dtr) -{ - asm volatile("lidt %0"::"m" (*dtr)); -} - -static inline void native_store_gdt(struct desc_ptr *dtr) -{ - asm volatile("sgdt %0":"=m" (*dtr)); -} - -static inline void native_store_idt(struct desc_ptr *dtr) -{ - asm volatile("sidt %0":"=m" (*dtr)); -} - -static inline unsigned long native_store_tr(void) -{ - unsigned long tr; - - asm volatile("str %0":"=r" (tr)); - - return tr; -} - -static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) -{ - struct desc_struct *gdt = get_cpu_gdt_table(cpu); - unsigned int i; - - for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) - gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; -} - /* This intentionally ignores lm, since 32-bit apps don't have that field. */ #define LDT_empty(info) \ ((info)->base_addr == 0 && \ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index 85599ad4d024..5dff775af7cd 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -36,6 +36,12 @@ # define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31)) #endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ +#ifdef CONFIG_X86_5LEVEL +# define DISABLE_LA57 0 +#else +# define DISABLE_LA57 (1<<(X86_FEATURE_LA57 & 31)) +#endif + /* * Make sure to add features to the correct mask */ @@ -55,7 +61,7 @@ #define DISABLED_MASK13 0 #define DISABLED_MASK14 0 #define DISABLED_MASK15 0 -#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE) +#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57) #define DISABLED_MASK17 0 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h deleted file mode 100644 index 67313f3a9874..000000000000 --- a/arch/x86/include/asm/e820.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _ASM_X86_E820_H -#define _ASM_X86_E820_H - -/* - * E820_X_MAX is the maximum size of the extended E820 table. The extended - * table may contain up to 3 extra E820 entries per possible NUMA node, so we - * make room for 3 * MAX_NUMNODES possible entries, beyond the standard 128. - * Also note that E820_X_MAX *must* be defined before we include uapi/asm/e820.h. - */ -#include <linux/numa.h> -#define E820_X_MAX (E820MAX + 3 * MAX_NUMNODES) - -#include <uapi/asm/e820.h> - -#ifndef __ASSEMBLY__ -/* see comment in arch/x86/kernel/e820.c */ -extern struct e820map *e820; -extern struct e820map *e820_saved; - -extern unsigned long pci_mem_start; -extern int e820_any_mapped(u64 start, u64 end, unsigned type); -extern int e820_all_mapped(u64 start, u64 end, unsigned type); -extern void e820_add_region(u64 start, u64 size, int type); -extern void e820_print_map(char *who); -extern int -sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map); -extern u64 e820_update_range(u64 start, u64 size, unsigned old_type, - unsigned new_type); -extern u64 e820_remove_range(u64 start, u64 size, unsigned old_type, - int checktype); -extern void update_e820(void); -extern void e820_setup_gap(void); -struct setup_data; -extern void parse_e820_ext(u64 phys_addr, u32 data_len); - -#if defined(CONFIG_X86_64) || \ - (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) -extern void e820_mark_nosave_regions(unsigned long limit_pfn); -#else -static inline void e820_mark_nosave_regions(unsigned long limit_pfn) -{ -} -#endif - -extern unsigned long e820_end_of_ram_pfn(void); -extern unsigned long e820_end_of_low_ram_pfn(void); -extern u64 early_reserve_e820(u64 sizet, u64 align); - -void memblock_x86_fill(void); -void memblock_find_dma_reserve(void); - -extern void finish_e820_parsing(void); -extern void e820_reserve_resources(void); -extern void e820_reserve_resources_late(void); -extern void setup_memory_map(void); -extern char *default_machine_specific_memory_setup(void); - -extern void e820_reallocate_tables(void); - -/* - * Returns true iff the specified range [s,e) is completely contained inside - * the ISA region. - */ -static inline bool is_ISA_range(u64 s, u64 e) -{ - return s >= ISA_START_ADDRESS && e <= ISA_END_ADDRESS; -} - -#endif /* __ASSEMBLY__ */ -#include <linux/ioport.h> - -#define HIGH_MEMORY (1024*1024) -#endif /* _ASM_X86_E820_H */ diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h new file mode 100644 index 000000000000..8e0f8b85b209 --- /dev/null +++ b/arch/x86/include/asm/e820/api.h @@ -0,0 +1,50 @@ +#ifndef _ASM_E820_API_H +#define _ASM_E820_API_H + +#include <asm/e820/types.h> + +extern struct e820_table *e820_table; +extern struct e820_table *e820_table_firmware; + +extern unsigned long pci_mem_start; + +extern bool e820__mapped_any(u64 start, u64 end, enum e820_type type); +extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type); + +extern void e820__range_add (u64 start, u64 size, enum e820_type type); +extern u64 e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type); +extern u64 e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type); + +extern void e820__print_table(char *who); +extern int e820__update_table(struct e820_table *table); +extern void e820__update_table_print(void); + +extern unsigned long e820__end_of_ram_pfn(void); +extern unsigned long e820__end_of_low_ram_pfn(void); + +extern u64 e820__memblock_alloc_reserved(u64 size, u64 align); +extern void e820__memblock_setup(void); + +extern void e820__reserve_setup_data(void); +extern void e820__finish_early_params(void); +extern void e820__reserve_resources(void); +extern void e820__reserve_resources_late(void); + +extern void e820__memory_setup(void); +extern void e820__memory_setup_extended(u64 phys_addr, u32 data_len); +extern char *e820__memory_setup_default(void); +extern void e820__setup_pci_gap(void); + +extern void e820__reallocate_tables(void); +extern void e820__register_nosave_regions(unsigned long limit_pfn); + +/* + * Returns true iff the specified range [start,end) is completely contained inside + * the ISA region. + */ +static inline bool is_ISA_range(u64 start, u64 end) +{ + return start >= ISA_START_ADDRESS && end <= ISA_END_ADDRESS; +} + +#endif /* _ASM_E820_API_H */ diff --git a/arch/x86/include/asm/e820/types.h b/arch/x86/include/asm/e820/types.h new file mode 100644 index 000000000000..4adeed03a9a1 --- /dev/null +++ b/arch/x86/include/asm/e820/types.h @@ -0,0 +1,104 @@ +#ifndef _ASM_E820_TYPES_H +#define _ASM_E820_TYPES_H + +#include <uapi/asm/bootparam.h> + +/* + * These are the E820 types known to the kernel: + */ +enum e820_type { + E820_TYPE_RAM = 1, + E820_TYPE_RESERVED = 2, + E820_TYPE_ACPI = 3, + E820_TYPE_NVS = 4, + E820_TYPE_UNUSABLE = 5, + E820_TYPE_PMEM = 7, + + /* + * This is a non-standardized way to represent ADR or + * NVDIMM regions that persist over a reboot. + * + * The kernel will ignore their special capabilities + * unless the CONFIG_X86_PMEM_LEGACY=y option is set. + * + * ( Note that older platforms also used 6 for the same + * type of memory, but newer versions switched to 12 as + * 6 was assigned differently. Some time they will learn... ) + */ + E820_TYPE_PRAM = 12, + + /* + * Reserved RAM used by the kernel itself if + * CONFIG_INTEL_TXT=y is enabled, memory of this type + * will be included in the S3 integrity calculation + * and so should not include any memory that the BIOS + * might alter over the S3 transition: + */ + E820_TYPE_RESERVED_KERN = 128, +}; + +/* + * A single E820 map entry, describing a memory range of [addr...addr+size-1], + * of 'type' memory type: + * + * (We pack it because there can be thousands of them on large systems.) + */ +struct e820_entry { + u64 addr; + u64 size; + enum e820_type type; +} __attribute__((packed)); + +/* + * The legacy E820 BIOS limits us to 128 (E820_MAX_ENTRIES_ZEROPAGE) nodes + * due to the constrained space in the zeropage. + * + * On large systems we can easily have thousands of nodes with RAM, + * which cannot be fit into so few entries - so we have a mechanism + * to extend the e820 table size at build-time, via the E820_MAX_ENTRIES + * define below. + * + * ( Those extra entries are enumerated via the EFI memory map, not + * via the legacy zeropage mechanism. ) + * + * Size our internal memory map tables to have room for these additional + * entries, based on a heuristic calculation: up to three entries per + * NUMA node, plus E820_MAX_ENTRIES_ZEROPAGE for some extra space. + * + * This allows for bootstrap/firmware quirks such as possible duplicate + * E820 entries that might need room in the same arrays, prior to the + * call to e820__update_table() to remove duplicates. The allowance + * of three memory map entries per node is "enough" entries for + * the initial hardware platform motivating this mechanism to make + * use of additional EFI map entries. Future platforms may want + * to allow more than three entries per node or otherwise refine + * this size. + */ + +#include <linux/numa.h> + +#define E820_MAX_ENTRIES (E820_MAX_ENTRIES_ZEROPAGE + 3*MAX_NUMNODES) + +/* + * The whole array of E820 entries: + */ +struct e820_table { + __u32 nr_entries; + struct e820_entry entries[E820_MAX_ENTRIES]; +}; + +/* + * Various well-known legacy memory ranges in physical memory: + */ +#define ISA_START_ADDRESS 0x000a0000 +#define ISA_END_ADDRESS 0x00100000 + +#define BIOS_BEGIN 0x000a0000 +#define BIOS_END 0x00100000 + +#define HIGH_MEMORY 0x00100000 + +#define BIOS_ROM_BASE 0xffe00000 +#define BIOS_ROM_END 0xffffffff + +#endif /* _ASM_E820_TYPES_H */ diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 9d49c18b5ea9..e8ab9a46bc68 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -287,14 +287,29 @@ struct task_struct; #define ARCH_DLINFO_IA32 \ do { \ - if (vdso32_enabled) { \ + if (VDSO_CURRENT_BASE) { \ NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \ } \ } while (0) +/* + * True on X86_32 or when emulating IA32 on X86_64 + */ +static inline int mmap_is_ia32(void) +{ + return IS_ENABLED(CONFIG_X86_32) || + (IS_ENABLED(CONFIG_COMPAT) && + test_thread_flag(TIF_ADDR32)); +} + +extern unsigned long tasksize_32bit(void); +extern unsigned long tasksize_64bit(void); +extern unsigned long get_mmap_base(int is_legacy); + #ifdef CONFIG_X86_32 +#define __STACK_RND_MASK(is32bit) (0x7ff) #define STACK_RND_MASK (0x7ff) #define ARCH_DLINFO ARCH_DLINFO_IA32 @@ -304,7 +319,8 @@ do { \ #else /* CONFIG_X86_32 */ /* 1GB for 64bit, 8MB for 32bit */ -#define STACK_RND_MASK (test_thread_flag(TIF_ADDR32) ? 0x7ff : 0x3fffff) +#define __STACK_RND_MASK(is32bit) ((is32bit) ? 0x7ff : 0x3fffff) +#define STACK_RND_MASK __STACK_RND_MASK(mmap_is_ia32()) #define ARCH_DLINFO \ do { \ @@ -348,16 +364,6 @@ extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp); #define compat_arch_setup_additional_pages compat_arch_setup_additional_pages -/* - * True on X86_32 or when emulating IA32 on X86_64 - */ -static inline int mmap_is_ia32(void) -{ - return IS_ENABLED(CONFIG_X86_32) || - (IS_ENABLED(CONFIG_COMPAT) && - test_thread_flag(TIF_ADDR32)); -} - /* Do not change the values. See get_align_mask() */ enum align_flags { ALIGN_VA_32 = BIT(0), diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 8554f960e21b..b65155cc3760 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -100,6 +100,10 @@ enum fixed_addresses { #ifdef CONFIG_X86_INTEL_MID FIX_LNW_VRTC, #endif + /* Fixmap entries to remap the GDTs, one per processor. */ + FIX_GDT_REMAP_BEGIN, + FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1, + __end_of_permanent_fixed_addresses, /* diff --git a/arch/x86/include/asm/gart.h b/arch/x86/include/asm/gart.h index 156cd5d18d2a..1d268098ac2e 100644 --- a/arch/x86/include/asm/gart.h +++ b/arch/x86/include/asm/gart.h @@ -1,7 +1,7 @@ #ifndef _ASM_X86_GART_H #define _ASM_X86_GART_H -#include <asm/e820.h> +#include <asm/e820/api.h> extern void set_up_gart_resume(u32, u32); @@ -97,7 +97,7 @@ static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size) printk(KERN_INFO "Aperture beyond 4GB. Ignoring.\n"); return 0; } - if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { + if (e820__mapped_any(aper_base, aper_base + aper_size, E820_TYPE_RAM)) { printk(KERN_INFO "Aperture pointing to e820 RAM. Ignoring.\n"); return 0; } diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index 9814db42b790..75b748a1deb8 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -12,6 +12,7 @@ */ #define INTEL_FAM6_CORE_YONAH 0x0E + #define INTEL_FAM6_CORE2_MEROM 0x0F #define INTEL_FAM6_CORE2_MEROM_L 0x16 #define INTEL_FAM6_CORE2_PENRYN 0x17 @@ -21,6 +22,7 @@ #define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ #define INTEL_FAM6_NEHALEM_EP 0x1A #define INTEL_FAM6_NEHALEM_EX 0x2E + #define INTEL_FAM6_WESTMERE 0x25 #define INTEL_FAM6_WESTMERE_EP 0x2C #define INTEL_FAM6_WESTMERE_EX 0x2F @@ -36,9 +38,9 @@ #define INTEL_FAM6_HASWELL_GT3E 0x46 #define INTEL_FAM6_BROADWELL_CORE 0x3D -#define INTEL_FAM6_BROADWELL_XEON_D 0x56 #define INTEL_FAM6_BROADWELL_GT3E 0x47 #define INTEL_FAM6_BROADWELL_X 0x4F +#define INTEL_FAM6_BROADWELL_XEON_D 0x56 #define INTEL_FAM6_SKYLAKE_MOBILE 0x4E #define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E @@ -59,8 +61,8 @@ #define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */ #define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */ #define INTEL_FAM6_ATOM_GOLDMONT 0x5C -#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A #define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ +#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A /* Xeon Phi */ diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 0d64397cee58..597dc4995678 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -12,6 +12,7 @@ #define IA32_L3_QOS_CFG 0xc81 #define IA32_L3_CBM_BASE 0xc90 #define IA32_L2_CBM_BASE 0xd10 +#define IA32_MBA_THRTL_BASE 0xd50 #define L3_QOS_CDP_ENABLE 0x01ULL @@ -37,23 +38,30 @@ struct rdtgroup { /* rdtgroup.flags */ #define RDT_DELETED 1 +/* rftype.flags */ +#define RFTYPE_FLAGS_CPUS_LIST 1 + /* List of all resource groups */ extern struct list_head rdt_all_groups; +extern int max_name_width, max_data_width; + int __init rdtgroup_init(void); /** * struct rftype - describe each file in the resctrl file system - * @name: file name - * @mode: access mode - * @kf_ops: operations - * @seq_show: show content of the file - * @write: write to the file + * @name: File name + * @mode: Access mode + * @kf_ops: File operations + * @flags: File specific RFTYPE_FLAGS_* flags + * @seq_show: Show content of the file + * @write: Write to the file */ struct rftype { char *name; umode_t mode; struct kernfs_ops *kf_ops; + unsigned long flags; int (*seq_show)(struct kernfs_open_file *of, struct seq_file *sf, void *v); @@ -67,54 +75,21 @@ struct rftype { }; /** - * struct rdt_resource - attributes of an RDT resource - * @enabled: Is this feature enabled on this machine - * @capable: Is this feature available on this machine - * @name: Name to use in "schemata" file - * @num_closid: Number of CLOSIDs available - * @max_cbm: Largest Cache Bit Mask allowed - * @min_cbm_bits: Minimum number of consecutive bits to be set - * in a cache bit mask - * @domains: All domains for this resource - * @num_domains: Number of domains active - * @msr_base: Base MSR address for CBMs - * @tmp_cbms: Scratch space when updating schemata - * @num_tmp_cbms: Number of CBMs in tmp_cbms - * @cache_level: Which cache level defines scope of this domain - * @cbm_idx_multi: Multiplier of CBM index - * @cbm_idx_offset: Offset of CBM index. CBM index is computed by: - * closid * cbm_idx_multi + cbm_idx_offset - */ -struct rdt_resource { - bool enabled; - bool capable; - char *name; - int num_closid; - int cbm_len; - int min_cbm_bits; - u32 max_cbm; - struct list_head domains; - int num_domains; - int msr_base; - u32 *tmp_cbms; - int num_tmp_cbms; - int cache_level; - int cbm_idx_multi; - int cbm_idx_offset; -}; - -/** * struct rdt_domain - group of cpus sharing an RDT resource * @list: all instances of this resource * @id: unique id for this instance * @cpu_mask: which cpus share this resource - * @cbm: array of cache bit masks (indexed by CLOSID) + * @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID) + * @new_ctrl: new ctrl value to be loaded + * @have_new_ctrl: did user provide new_ctrl for this domain */ struct rdt_domain { struct list_head list; int id; struct cpumask cpu_mask; - u32 *cbm; + u32 *ctrl_val; + u32 new_ctrl; + bool have_new_ctrl; }; /** @@ -129,6 +104,83 @@ struct msr_param { int high; }; +/** + * struct rdt_cache - Cache allocation related data + * @cbm_len: Length of the cache bit mask + * @min_cbm_bits: Minimum number of consecutive bits to be set + * @cbm_idx_mult: Multiplier of CBM index + * @cbm_idx_offset: Offset of CBM index. CBM index is computed by: + * closid * cbm_idx_multi + cbm_idx_offset + * in a cache bit mask + */ +struct rdt_cache { + unsigned int cbm_len; + unsigned int min_cbm_bits; + unsigned int cbm_idx_mult; + unsigned int cbm_idx_offset; +}; + +/** + * struct rdt_membw - Memory bandwidth allocation related data + * @max_delay: Max throttle delay. Delay is the hardware + * representation for memory bandwidth. + * @min_bw: Minimum memory bandwidth percentage user can request + * @bw_gran: Granularity at which the memory bandwidth is allocated + * @delay_linear: True if memory B/W delay is in linear scale + * @mb_map: Mapping of memory B/W percentage to memory B/W delay + */ +struct rdt_membw { + u32 max_delay; + u32 min_bw; + u32 bw_gran; + u32 delay_linear; + u32 *mb_map; +}; + +/** + * struct rdt_resource - attributes of an RDT resource + * @enabled: Is this feature enabled on this machine + * @capable: Is this feature available on this machine + * @name: Name to use in "schemata" file + * @num_closid: Number of CLOSIDs available + * @cache_level: Which cache level defines scope of this resource + * @default_ctrl: Specifies default cache cbm or memory B/W percent. + * @msr_base: Base MSR address for CBMs + * @msr_update: Function pointer to update QOS MSRs + * @data_width: Character width of data when displaying + * @domains: All domains for this resource + * @cache: Cache allocation related data + * @info_files: resctrl info files for the resource + * @nr_info_files: Number of info files + * @format_str: Per resource format string to show domain value + * @parse_ctrlval: Per resource function pointer to parse control values + */ +struct rdt_resource { + bool enabled; + bool capable; + char *name; + int num_closid; + int cache_level; + u32 default_ctrl; + unsigned int msr_base; + void (*msr_update) (struct rdt_domain *d, struct msr_param *m, + struct rdt_resource *r); + int data_width; + struct list_head domains; + struct rdt_cache cache; + struct rdt_membw membw; + struct rftype *info_files; + int nr_info_files; + const char *format_str; + int (*parse_ctrlval) (char *buf, struct rdt_resource *r, + struct rdt_domain *d); +}; + +void rdt_get_cache_infofile(struct rdt_resource *r); +void rdt_get_mba_infofile(struct rdt_resource *r); +int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d); +int parse_bw(char *buf, struct rdt_resource *r, struct rdt_domain *d); + extern struct mutex rdtgroup_mutex; extern struct rdt_resource rdt_resources_all[]; @@ -142,6 +194,7 @@ enum { RDT_RESOURCE_L3DATA, RDT_RESOURCE_L3CODE, RDT_RESOURCE_L2, + RDT_RESOURCE_MBA, /* Must be the last */ RDT_NUM_RESOURCES, @@ -149,7 +202,7 @@ enum { #define for_each_capable_rdt_resource(r) \ for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\ - r++) \ + r++) \ if (r->capable) #define for_each_enabled_rdt_resource(r) \ @@ -165,8 +218,16 @@ union cpuid_0x10_1_eax { unsigned int full; }; -/* CPUID.(EAX=10H, ECX=ResID=1).EDX */ -union cpuid_0x10_1_edx { +/* CPUID.(EAX=10H, ECX=ResID=3).EAX */ +union cpuid_0x10_3_eax { + struct { + unsigned int max_delay:12; + } split; + unsigned int full; +}; + +/* CPUID.(EAX=10H, ECX=ResID).EDX */ +union cpuid_0x10_x_edx { struct { unsigned int cos_max:16; } split; @@ -175,7 +236,7 @@ union cpuid_0x10_1_edx { DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid); -void rdt_cbm_update(void *arg); +void rdt_ctrl_update(void *arg); struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn); void rdtgroup_kn_unlock(struct kernfs_node *kn); ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h index 1410b567ecde..f527b02a0ee3 100644 --- a/arch/x86/include/asm/kasan.h +++ b/arch/x86/include/asm/kasan.h @@ -11,9 +11,12 @@ * 'kernel address space start' >> KASAN_SHADOW_SCALE_SHIFT */ #define KASAN_SHADOW_START (KASAN_SHADOW_OFFSET + \ - (0xffff800000000000ULL >> 3)) -/* 47 bits for kernel address -> (47 - 3) bits for shadow */ -#define KASAN_SHADOW_END (KASAN_SHADOW_START + (1ULL << (47 - 3))) + ((-1UL << __VIRTUAL_MASK_SHIFT) >> 3)) +/* + * 47 bits for kernel address -> (47 - 3) bits for shadow + * 56 bits for kernel address -> (56 - 3) bits for shadow + */ +#define KASAN_SHADOW_END (KASAN_SHADOW_START + (1ULL << (__VIRTUAL_MASK_SHIFT - 3))) #ifndef __ASSEMBLY__ diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h index 282630e4c6ea..70ef205489f0 100644 --- a/arch/x86/include/asm/kexec.h +++ b/arch/x86/include/asm/kexec.h @@ -164,6 +164,7 @@ struct kimage_arch { }; #else struct kimage_arch { + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h index 200581691c6e..34b984c60790 100644 --- a/arch/x86/include/asm/kprobes.h +++ b/arch/x86/include/asm/kprobes.h @@ -72,14 +72,13 @@ struct arch_specific_insn { /* copy of the original instruction */ kprobe_opcode_t *insn; /* - * boostable = -1: This instruction type is not boostable. - * boostable = 0: This instruction type is boostable. - * boostable = 1: This instruction has been boosted: we have + * boostable = false: This instruction type is not boostable. + * boostable = true: This instruction has been boosted: we have * added a relative jump after the instruction copy in insn, * so no single-step and fixup are needed (unless there's * a post_handler or break_handler). */ - int boostable; + bool boostable; bool if_modifier; }; diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h index d74747b031ec..c4eda791f877 100644 --- a/arch/x86/include/asm/kvm_page_track.h +++ b/arch/x86/include/asm/kvm_page_track.h @@ -46,6 +46,7 @@ struct kvm_page_track_notifier_node { }; void kvm_page_track_init(struct kvm *kvm); +void kvm_page_track_cleanup(struct kvm *kvm); void kvm_page_track_free_memslot(struct kvm_memory_slot *free, struct kvm_memory_slot *dont); diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index e63873683d4a..4fd5195deed0 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -128,7 +128,7 @@ * debugging tools. Each entry is only valid when its finished flag * is set. */ -struct mce_log { +struct mce_log_buffer { char signature[12]; /* "MACHINECHECK" */ unsigned len; /* = MCE_LOG_LEN */ unsigned next; @@ -191,10 +191,12 @@ extern struct mca_config mca_cfg; extern struct mca_msr_regs msr_ops; enum mce_notifier_prios { - MCE_PRIO_SRAO = INT_MAX, - MCE_PRIO_EXTLOG = INT_MAX - 1, - MCE_PRIO_NFIT = INT_MAX - 2, - MCE_PRIO_EDAC = INT_MAX - 3, + MCE_PRIO_FIRST = INT_MAX, + MCE_PRIO_SRAO = INT_MAX - 1, + MCE_PRIO_EXTLOG = INT_MAX - 2, + MCE_PRIO_NFIT = INT_MAX - 3, + MCE_PRIO_EDAC = INT_MAX - 4, + MCE_PRIO_MCELOG = 1, MCE_PRIO_LOWEST = 0, }; diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 306c7e12af55..68b329d77b3a 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -268,8 +268,4 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, return __pkru_allows_pkey(vma_pkey(vma), write); } -static inline bool arch_pte_access_permitted(pte_t pte, bool write) -{ - return __pkru_allows_pkey(pte_flags_pkey(pte_flags(pte)), write); -} #endif /* _ASM_X86_MMU_CONTEXT_H */ diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 32007041ef8c..831eb7895535 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -64,7 +64,7 @@ static inline void find_smp_config(void) } #ifdef CONFIG_X86_MPPARSE -extern void early_reserve_e820_mpc_new(void); +extern void e820__memblock_alloc_reserved_mpc_new(void); extern int enable_update_mptable; extern int default_mpc_apic_id(struct mpc_cpu *m); extern void default_smp_read_mpc_oem(struct mpc_table *mpc); @@ -76,7 +76,7 @@ extern void default_mpc_oem_bus_info(struct mpc_bus *m, char *str); extern void default_find_smp_config(void); extern void default_get_smp_config(unsigned int early); #else -static inline void early_reserve_e820_mpc_new(void) { } +static inline void e820__memblock_alloc_reserved_mpc_new(void) { } #define enable_update_mptable 0 #define default_mpc_apic_id NULL #define default_smp_read_mpc_oem NULL diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 7c9c895432a9..fba100713924 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -176,4 +176,58 @@ void hyperv_report_panic(struct pt_regs *regs); bool hv_is_hypercall_page_setup(void); void hyperv_cleanup(void); #endif +#ifdef CONFIG_HYPERV_TSCPAGE +struct ms_hyperv_tsc_page *hv_get_tsc_page(void); +static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) +{ + u64 scale, offset, cur_tsc; + u32 sequence; + + /* + * The protocol for reading Hyper-V TSC page is specified in Hypervisor + * Top-Level Functional Specification ver. 3.0 and above. To get the + * reference time we must do the following: + * - READ ReferenceTscSequence + * A special '0' value indicates the time source is unreliable and we + * need to use something else. The currently published specification + * versions (up to 4.0b) contain a mistake and wrongly claim '-1' + * instead of '0' as the special value, see commit c35b82ef0294. + * - ReferenceTime = + * ((RDTSC() * ReferenceTscScale) >> 64) + ReferenceTscOffset + * - READ ReferenceTscSequence again. In case its value has changed + * since our first reading we need to discard ReferenceTime and repeat + * the whole sequence as the hypervisor was updating the page in + * between. + */ + do { + sequence = READ_ONCE(tsc_pg->tsc_sequence); + if (!sequence) + return U64_MAX; + /* + * Make sure we read sequence before we read other values from + * TSC page. + */ + smp_rmb(); + + scale = READ_ONCE(tsc_pg->tsc_scale); + offset = READ_ONCE(tsc_pg->tsc_offset); + cur_tsc = rdtsc_ordered(); + + /* + * Make sure we read sequence after we read all other values + * from TSC page. + */ + smp_rmb(); + + } while (READ_ONCE(tsc_pg->tsc_sequence) != sequence); + + return mul_u64_u64_shr(cur_tsc, scale, 64) + offset; +} + +#else +static inline struct ms_hyperv_tsc_page *hv_get_tsc_page(void) +{ + return NULL; +} +#endif #endif diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index d8b5f8ab8ef9..673f9ac50f6d 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -45,6 +45,8 @@ #define MSR_IA32_PERFCTR1 0x000000c2 #define MSR_FSB_FREQ 0x000000cd #define MSR_PLATFORM_INFO 0x000000ce +#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT 31 +#define MSR_PLATFORM_INFO_CPUID_FAULT BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT) #define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 #define NHM_C3_AUTO_DEMOTE (1UL << 25) @@ -127,6 +129,7 @@ /* DEBUGCTLMSR bits (others vary by model): */ #define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ +#define DEBUGCTLMSR_BTF_SHIFT 1 #define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ #define DEBUGCTLMSR_TR (1UL << 6) #define DEBUGCTLMSR_BTS (1UL << 7) @@ -552,10 +555,12 @@ #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT 39 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT) -/* MISC_FEATURE_ENABLES non-architectural features */ -#define MSR_MISC_FEATURE_ENABLES 0x00000140 +/* MISC_FEATURES_ENABLES non-architectural features */ +#define MSR_MISC_FEATURES_ENABLES 0x00000140 -#define MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT 1 +#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT 0 +#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT) +#define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT 1 #define MSR_IA32_TSC_DEADLINE 0x000006E0 diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index b3bebf9e5746..b4a0d43248cf 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h @@ -4,6 +4,7 @@ #include <asm/page_64_types.h> #ifndef __ASSEMBLY__ +#include <asm/alternative.h> /* duplicated to the one in bootmem.h */ extern unsigned long max_pfn; @@ -34,7 +35,20 @@ extern unsigned long __phys_addr_symbol(unsigned long); #define pfn_valid(pfn) ((pfn) < max_pfn) #endif -void clear_page(void *page); +void clear_page_orig(void *page); +void clear_page_rep(void *page); +void clear_page_erms(void *page); + +static inline void clear_page(void *page) +{ + alternative_call_2(clear_page_orig, + clear_page_rep, X86_FEATURE_REP_GOOD, + clear_page_erms, X86_FEATURE_ERMS, + "=D" (page), + "0" (page) + : "memory", "rax", "rcx"); +} + void copy_page(void *to, void *from); #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h index 9215e0527647..3f5f08b010d0 100644 --- a/arch/x86/include/asm/page_64_types.h +++ b/arch/x86/include/asm/page_64_types.h @@ -36,7 +36,12 @@ * hypervisor to fit. Choosing 16 slots here is arbitrary, but it's * what Xen requires. */ +#ifdef CONFIG_X86_5LEVEL +#define __PAGE_OFFSET_BASE _AC(0xff10000000000000, UL) +#else #define __PAGE_OFFSET_BASE _AC(0xffff880000000000, UL) +#endif + #ifdef CONFIG_RANDOMIZE_MEMORY #define __PAGE_OFFSET page_offset_base #else @@ -46,8 +51,13 @@ #define __START_KERNEL_map _AC(0xffffffff80000000, UL) /* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */ +#ifdef CONFIG_X86_5LEVEL +#define __PHYSICAL_MASK_SHIFT 52 +#define __VIRTUAL_MASK_SHIFT 56 +#else #define __PHYSICAL_MASK_SHIFT 46 #define __VIRTUAL_MASK_SHIFT 47 +#endif /* * Kernel image size is limited to 1GiB due to the fixmap living in the diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 0489884fdc44..55fa56fe4e45 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -357,6 +357,16 @@ static inline void paravirt_release_pud(unsigned long pfn) PVOP_VCALL1(pv_mmu_ops.release_pud, pfn); } +static inline void paravirt_alloc_p4d(struct mm_struct *mm, unsigned long pfn) +{ + PVOP_VCALL2(pv_mmu_ops.alloc_p4d, mm, pfn); +} + +static inline void paravirt_release_p4d(unsigned long pfn) +{ + PVOP_VCALL1(pv_mmu_ops.release_p4d, pfn); +} + static inline void pte_update(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -536,7 +546,7 @@ static inline void set_pud(pud_t *pudp, pud_t pud) PVOP_VCALL2(pv_mmu_ops.set_pud, pudp, val); } -#if CONFIG_PGTABLE_LEVELS == 4 +#if CONFIG_PGTABLE_LEVELS >= 4 static inline pud_t __pud(pudval_t val) { pudval_t ret; @@ -565,26 +575,54 @@ static inline pudval_t pud_val(pud_t pud) return ret; } -static inline void set_pgd(pgd_t *pgdp, pgd_t pgd) +static inline void pud_clear(pud_t *pudp) { - pgdval_t val = native_pgd_val(pgd); + set_pud(pudp, __pud(0)); +} - if (sizeof(pgdval_t) > sizeof(long)) - PVOP_VCALL3(pv_mmu_ops.set_pgd, pgdp, +static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) +{ + p4dval_t val = native_p4d_val(p4d); + + if (sizeof(p4dval_t) > sizeof(long)) + PVOP_VCALL3(pv_mmu_ops.set_p4d, p4dp, val, (u64)val >> 32); else - PVOP_VCALL2(pv_mmu_ops.set_pgd, pgdp, + PVOP_VCALL2(pv_mmu_ops.set_p4d, p4dp, val); } +#if CONFIG_PGTABLE_LEVELS >= 5 + +static inline p4d_t __p4d(p4dval_t val) +{ + p4dval_t ret = PVOP_CALLEE1(p4dval_t, pv_mmu_ops.make_p4d, val); + + return (p4d_t) { ret }; +} + +static inline p4dval_t p4d_val(p4d_t p4d) +{ + return PVOP_CALLEE1(p4dval_t, pv_mmu_ops.p4d_val, p4d.p4d); +} + +static inline void set_pgd(pgd_t *pgdp, pgd_t pgd) +{ + pgdval_t val = native_pgd_val(pgd); + + PVOP_VCALL2(pv_mmu_ops.set_pgd, pgdp, val); +} + static inline void pgd_clear(pgd_t *pgdp) { set_pgd(pgdp, __pgd(0)); } -static inline void pud_clear(pud_t *pudp) +#endif /* CONFIG_PGTABLE_LEVELS == 5 */ + +static inline void p4d_clear(p4d_t *p4dp) { - set_pud(pudp, __pud(0)); + set_p4d(p4dp, __p4d(0)); } #endif /* CONFIG_PGTABLE_LEVELS == 4 */ diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index b060f962d581..7465d6fe336f 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -238,9 +238,11 @@ struct pv_mmu_ops { void (*alloc_pte)(struct mm_struct *mm, unsigned long pfn); void (*alloc_pmd)(struct mm_struct *mm, unsigned long pfn); void (*alloc_pud)(struct mm_struct *mm, unsigned long pfn); + void (*alloc_p4d)(struct mm_struct *mm, unsigned long pfn); void (*release_pte)(unsigned long pfn); void (*release_pmd)(unsigned long pfn); void (*release_pud)(unsigned long pfn); + void (*release_p4d)(unsigned long pfn); /* Pagetable manipulation functions */ void (*set_pte)(pte_t *ptep, pte_t pteval); @@ -279,12 +281,21 @@ struct pv_mmu_ops { struct paravirt_callee_save pmd_val; struct paravirt_callee_save make_pmd; -#if CONFIG_PGTABLE_LEVELS == 4 +#if CONFIG_PGTABLE_LEVELS >= 4 struct paravirt_callee_save pud_val; struct paravirt_callee_save make_pud; - void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); -#endif /* CONFIG_PGTABLE_LEVELS == 4 */ + void (*set_p4d)(p4d_t *p4dp, p4d_t p4dval); + +#if CONFIG_PGTABLE_LEVELS >= 5 + struct paravirt_callee_save p4d_val; + struct paravirt_callee_save make_p4d; + + void (*set_pgd)(pgd_t *pgdp, pgd_t pgdval); +#endif /* CONFIG_PGTABLE_LEVELS >= 5 */ + +#endif /* CONFIG_PGTABLE_LEVELS >= 4 */ + #endif /* CONFIG_PGTABLE_LEVELS >= 3 */ struct pv_lazy_ops lazy_mode; diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index d08eacd298c2..9f1b21f372fe 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -4,6 +4,8 @@ * (c) 1999 Martin Mares <mj@ucw.cz> */ +#include <linux/ioport.h> + #undef DEBUG #ifdef DEBUG diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h index b6d425999f99..b2d0cd8288aa 100644 --- a/arch/x86/include/asm/pgalloc.h +++ b/arch/x86/include/asm/pgalloc.h @@ -17,9 +17,11 @@ static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn) { static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count) {} static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn) {} +static inline void paravirt_alloc_p4d(struct mm_struct *mm, unsigned long pfn) {} static inline void paravirt_release_pte(unsigned long pfn) {} static inline void paravirt_release_pmd(unsigned long pfn) {} static inline void paravirt_release_pud(unsigned long pfn) {} +static inline void paravirt_release_p4d(unsigned long pfn) {} #endif /* @@ -121,10 +123,10 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) #endif /* CONFIG_X86_PAE */ #if CONFIG_PGTABLE_LEVELS > 3 -static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) +static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud) { paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT); - set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))); + set_p4d(p4d, __p4d(_PAGE_TABLE | __pa(pud))); } static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) @@ -150,6 +152,37 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, ___pud_free_tlb(tlb, pud); } +#if CONFIG_PGTABLE_LEVELS > 4 +static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d) +{ + paravirt_alloc_p4d(mm, __pa(p4d) >> PAGE_SHIFT); + set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(p4d))); +} + +static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr) +{ + gfp_t gfp = GFP_KERNEL_ACCOUNT; + + if (mm == &init_mm) + gfp &= ~__GFP_ACCOUNT; + return (p4d_t *)get_zeroed_page(gfp); +} + +static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d) +{ + BUG_ON((unsigned long)p4d & (PAGE_SIZE-1)); + free_page((unsigned long)p4d); +} + +extern void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d); + +static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d, + unsigned long address) +{ + ___p4d_free_tlb(tlb, p4d); +} + +#endif /* CONFIG_PGTABLE_LEVELS > 4 */ #endif /* CONFIG_PGTABLE_LEVELS > 3 */ #endif /* CONFIG_PGTABLE_LEVELS > 2 */ diff --git a/arch/x86/include/asm/pgtable-2level_types.h b/arch/x86/include/asm/pgtable-2level_types.h index 392576433e77..373ab1de909f 100644 --- a/arch/x86/include/asm/pgtable-2level_types.h +++ b/arch/x86/include/asm/pgtable-2level_types.h @@ -7,6 +7,7 @@ typedef unsigned long pteval_t; typedef unsigned long pmdval_t; typedef unsigned long pudval_t; +typedef unsigned long p4dval_t; typedef unsigned long pgdval_t; typedef unsigned long pgprotval_t; diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 72277b1028a5..50d35e3185f5 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -121,12 +121,9 @@ static inline void native_pmd_clear(pmd_t *pmd) *(tmp + 1) = 0; } -#if !defined(CONFIG_SMP) || (defined(CONFIG_HIGHMEM64G) && \ - defined(CONFIG_PARAVIRT)) static inline void native_pud_clear(pud_t *pudp) { } -#endif static inline void pud_clear(pud_t *pudp) { diff --git a/arch/x86/include/asm/pgtable-3level_types.h b/arch/x86/include/asm/pgtable-3level_types.h index bcc89625ebe5..b8a4341faafa 100644 --- a/arch/x86/include/asm/pgtable-3level_types.h +++ b/arch/x86/include/asm/pgtable-3level_types.h @@ -7,6 +7,7 @@ typedef u64 pteval_t; typedef u64 pmdval_t; typedef u64 pudval_t; +typedef u64 p4dval_t; typedef u64 pgdval_t; typedef u64 pgprotval_t; diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 1cfb36b8c024..f5af95a0c6b8 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -2,8 +2,6 @@ #define _ASM_X86_PGTABLE_H #include <asm/page.h> -#include <asm/e820.h> - #include <asm/pgtable_types.h> /* @@ -53,16 +51,24 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); #define set_pmd(pmdp, pmd) native_set_pmd(pmdp, pmd) -#ifndef __PAGETABLE_PUD_FOLDED +#ifndef __PAGETABLE_P4D_FOLDED #define set_pgd(pgdp, pgd) native_set_pgd(pgdp, pgd) #define pgd_clear(pgd) native_pgd_clear(pgd) #endif +#ifndef set_p4d +# define set_p4d(p4dp, p4d) native_set_p4d(p4dp, p4d) +#endif + +#ifndef __PAGETABLE_PUD_FOLDED +#define p4d_clear(p4d) native_p4d_clear(p4d) +#endif + #ifndef set_pud # define set_pud(pudp, pud) native_set_pud(pudp, pud) #endif -#ifndef __PAGETABLE_PMD_FOLDED +#ifndef __PAGETABLE_PUD_FOLDED #define pud_clear(pud) native_pud_clear(pud) #endif @@ -74,6 +80,11 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); #define pgd_val(x) native_pgd_val(x) #define __pgd(x) native_make_pgd(x) +#ifndef __PAGETABLE_P4D_FOLDED +#define p4d_val(x) native_p4d_val(x) +#define __p4d(x) native_make_p4d(x) +#endif + #ifndef __PAGETABLE_PUD_FOLDED #define pud_val(x) native_pud_val(x) #define __pud(x) native_make_pud(x) @@ -179,6 +190,17 @@ static inline unsigned long pud_pfn(pud_t pud) return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT; } +static inline unsigned long p4d_pfn(p4d_t p4d) +{ + return (p4d_val(p4d) & p4d_pfn_mask(p4d)) >> PAGE_SHIFT; +} + +static inline int p4d_large(p4d_t p4d) +{ + /* No 512 GiB pages yet */ + return 0; +} + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) static inline int pmd_large(pmd_t pte) @@ -538,6 +560,7 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) #define pte_pgprot(x) __pgprot(pte_flags(x)) #define pmd_pgprot(x) __pgprot(pmd_flags(x)) #define pud_pgprot(x) __pgprot(pud_flags(x)) +#define p4d_pgprot(x) __pgprot(p4d_flags(x)) #define canon_pgprot(p) __pgprot(massage_pgprot(p)) @@ -587,6 +610,7 @@ pte_t *populate_extra_pte(unsigned long vaddr); #include <linux/mm_types.h> #include <linux/mmdebug.h> #include <linux/log2.h> +#include <asm/fixmap.h> static inline int pte_none(pte_t pte) { @@ -770,7 +794,52 @@ static inline int pud_large(pud_t pud) } #endif /* CONFIG_PGTABLE_LEVELS > 2 */ +static inline unsigned long pud_index(unsigned long address) +{ + return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1); +} + #if CONFIG_PGTABLE_LEVELS > 3 +static inline int p4d_none(p4d_t p4d) +{ + return (native_p4d_val(p4d) & ~(_PAGE_KNL_ERRATUM_MASK)) == 0; +} + +static inline int p4d_present(p4d_t p4d) +{ + return p4d_flags(p4d) & _PAGE_PRESENT; +} + +static inline unsigned long p4d_page_vaddr(p4d_t p4d) +{ + return (unsigned long)__va(p4d_val(p4d) & p4d_pfn_mask(p4d)); +} + +/* + * Currently stuck as a macro due to indirect forward reference to + * linux/mmzone.h's __section_mem_map_addr() definition: + */ +#define p4d_page(p4d) \ + pfn_to_page((p4d_val(p4d) & p4d_pfn_mask(p4d)) >> PAGE_SHIFT) + +/* Find an entry in the third-level page table.. */ +static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address) +{ + return (pud_t *)p4d_page_vaddr(*p4d) + pud_index(address); +} + +static inline int p4d_bad(p4d_t p4d) +{ + return (p4d_flags(p4d) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0; +} +#endif /* CONFIG_PGTABLE_LEVELS > 3 */ + +static inline unsigned long p4d_index(unsigned long address) +{ + return (address >> P4D_SHIFT) & (PTRS_PER_P4D - 1); +} + +#if CONFIG_PGTABLE_LEVELS > 4 static inline int pgd_present(pgd_t pgd) { return pgd_flags(pgd) & _PAGE_PRESENT; @@ -788,14 +857,9 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) #define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT) /* to find an entry in a page-table-directory. */ -static inline unsigned long pud_index(unsigned long address) -{ - return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1); -} - -static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) +static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address) { - return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address); + return (p4d_t *)pgd_page_vaddr(*pgd) + p4d_index(address); } static inline int pgd_bad(pgd_t pgd) @@ -813,7 +877,7 @@ static inline int pgd_none(pgd_t pgd) */ return !native_pgd_val(pgd); } -#endif /* CONFIG_PGTABLE_LEVELS > 3 */ +#endif /* CONFIG_PGTABLE_LEVELS > 4 */ #endif /* __ASSEMBLY__ */ @@ -845,6 +909,7 @@ static inline int pgd_none(pgd_t pgd) extern int direct_gbpages; void init_mem_mapping(void); void early_alloc_pgt_buf(void); +extern void memblock_find_dma_reserve(void); #ifdef CONFIG_X86_64 /* Realmode trampoline initialization. */ diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index fbc73360aea0..bfab55675c16 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -14,7 +14,6 @@ */ #ifndef __ASSEMBLY__ #include <asm/processor.h> -#include <asm/fixmap.h> #include <linux/threads.h> #include <asm/paravirt.h> diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 73c7ccc38912..9991224f6238 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -35,15 +35,22 @@ extern void paging_init(void); #define pud_ERROR(e) \ pr_err("%s:%d: bad pud %p(%016lx)\n", \ __FILE__, __LINE__, &(e), pud_val(e)) + +#if CONFIG_PGTABLE_LEVELS >= 5 +#define p4d_ERROR(e) \ + pr_err("%s:%d: bad p4d %p(%016lx)\n", \ + __FILE__, __LINE__, &(e), p4d_val(e)) +#endif + #define pgd_ERROR(e) \ pr_err("%s:%d: bad pgd %p(%016lx)\n", \ __FILE__, __LINE__, &(e), pgd_val(e)) struct mm_struct; +void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pte_t new_pte); void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte); - static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -121,6 +128,20 @@ static inline pud_t native_pudp_get_and_clear(pud_t *xp) #endif } +static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d) +{ + *p4dp = p4d; +} + +static inline void native_p4d_clear(p4d_t *p4d) +{ +#ifdef CONFIG_X86_5LEVEL + native_set_p4d(p4d, native_make_p4d(0)); +#else + native_set_p4d(p4d, (p4d_t) { .pgd = native_make_pgd(0)}); +#endif +} + static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd) { *pgdp = pgd; diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h index 3a264200c62f..06470da156ba 100644 --- a/arch/x86/include/asm/pgtable_64_types.h +++ b/arch/x86/include/asm/pgtable_64_types.h @@ -13,6 +13,7 @@ typedef unsigned long pteval_t; typedef unsigned long pmdval_t; typedef unsigned long pudval_t; +typedef unsigned long p4dval_t; typedef unsigned long pgdval_t; typedef unsigned long pgprotval_t; @@ -22,12 +23,32 @@ typedef struct { pteval_t pte; } pte_t; #define SHARED_KERNEL_PMD 0 +#ifdef CONFIG_X86_5LEVEL + +/* + * PGDIR_SHIFT determines what a top-level page table entry can map + */ +#define PGDIR_SHIFT 48 +#define PTRS_PER_PGD 512 + +/* + * 4th level page in 5-level paging case + */ +#define P4D_SHIFT 39 +#define PTRS_PER_P4D 512 +#define P4D_SIZE (_AC(1, UL) << P4D_SHIFT) +#define P4D_MASK (~(P4D_SIZE - 1)) + +#else /* CONFIG_X86_5LEVEL */ + /* * PGDIR_SHIFT determines what a top-level page table entry can map */ #define PGDIR_SHIFT 39 #define PTRS_PER_PGD 512 +#endif /* CONFIG_X86_5LEVEL */ + /* * 3rd level page */ @@ -55,9 +76,15 @@ typedef struct { pteval_t pte; } pte_t; /* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */ #define MAXMEM _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL) +#ifdef CONFIG_X86_5LEVEL +#define VMALLOC_SIZE_TB _AC(16384, UL) +#define __VMALLOC_BASE _AC(0xff92000000000000, UL) +#define __VMEMMAP_BASE _AC(0xffd4000000000000, UL) +#else #define VMALLOC_SIZE_TB _AC(32, UL) #define __VMALLOC_BASE _AC(0xffffc90000000000, UL) #define __VMEMMAP_BASE _AC(0xffffea0000000000, UL) +#endif #ifdef CONFIG_RANDOMIZE_MEMORY #define VMALLOC_START vmalloc_base #define VMEMMAP_START vmemmap_base @@ -67,10 +94,11 @@ typedef struct { pteval_t pte; } pte_t; #endif /* CONFIG_RANDOMIZE_MEMORY */ #define VMALLOC_END (VMALLOC_START + _AC((VMALLOC_SIZE_TB << 40) - 1, UL)) #define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE) -#define MODULES_END _AC(0xffffffffff000000, UL) +/* The module sections ends with the start of the fixmap */ +#define MODULES_END __fix_to_virt(__end_of_fixed_addresses + 1) #define MODULES_LEN (MODULES_END - MODULES_VADDR) #define ESPFIX_PGD_ENTRY _AC(-2, UL) -#define ESPFIX_BASE_ADDR (ESPFIX_PGD_ENTRY << PGDIR_SHIFT) +#define ESPFIX_BASE_ADDR (ESPFIX_PGD_ENTRY << P4D_SHIFT) #define EFI_VA_START ( -4 * (_AC(1, UL) << 30)) #define EFI_VA_END (-68 * (_AC(1, UL) << 30)) diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 8b4de22d6429..bf9638e1ee42 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -272,6 +272,27 @@ static inline pgdval_t pgd_flags(pgd_t pgd) return native_pgd_val(pgd) & PTE_FLAGS_MASK; } +#if CONFIG_PGTABLE_LEVELS > 4 +typedef struct { p4dval_t p4d; } p4d_t; + +static inline p4d_t native_make_p4d(pudval_t val) +{ + return (p4d_t) { val }; +} + +static inline p4dval_t native_p4d_val(p4d_t p4d) +{ + return p4d.p4d; +} +#else +#include <asm-generic/pgtable-nop4d.h> + +static inline p4dval_t native_p4d_val(p4d_t p4d) +{ + return native_pgd_val(p4d.pgd); +} +#endif + #if CONFIG_PGTABLE_LEVELS > 3 typedef struct { pudval_t pud; } pud_t; @@ -289,7 +310,7 @@ static inline pudval_t native_pud_val(pud_t pud) static inline pudval_t native_pud_val(pud_t pud) { - return native_pgd_val(pud.pgd); + return native_pgd_val(pud.p4d.pgd); } #endif @@ -310,10 +331,26 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) static inline pmdval_t native_pmd_val(pmd_t pmd) { - return native_pgd_val(pmd.pud.pgd); + return native_pgd_val(pmd.pud.p4d.pgd); } #endif +static inline p4dval_t p4d_pfn_mask(p4d_t p4d) +{ + /* No 512 GiB huge pages yet */ + return PTE_PFN_MASK; +} + +static inline p4dval_t p4d_flags_mask(p4d_t p4d) +{ + return ~p4d_pfn_mask(p4d); +} + +static inline p4dval_t p4d_flags(p4d_t p4d) +{ + return native_p4d_val(p4d) & p4d_flags_mask(p4d); +} + static inline pudval_t pud_pfn_mask(pud_t pud) { if (native_pud_val(pud) & _PAGE_PSE) @@ -457,6 +494,7 @@ enum pg_level { PG_LEVEL_4K, PG_LEVEL_2M, PG_LEVEL_1G, + PG_LEVEL_512G, PG_LEVEL_NUM }; diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h index 34684adb6899..b3b09b98896d 100644 --- a/arch/x86/include/asm/pkeys.h +++ b/arch/x86/include/asm/pkeys.h @@ -46,6 +46,15 @@ extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey, static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) { + /* + * "Allocated" pkeys are those that have been returned + * from pkey_alloc(). pkey 0 is special, and never + * returned from pkey_alloc(). + */ + if (pkey <= 0) + return false; + if (pkey >= arch_max_pkey()) + return false; return mm_pkey_allocation_map(mm) & (1U << pkey); } @@ -82,12 +91,6 @@ int mm_pkey_alloc(struct mm_struct *mm) static inline int mm_pkey_free(struct mm_struct *mm, int pkey) { - /* - * pkey 0 is special, always allocated and can never - * be freed. - */ - if (!pkey) - return -EINVAL; if (!mm_pkey_is_allocated(mm, pkey)) return -EINVAL; diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h index 2c1ebeb4d737..529bb4a6487a 100644 --- a/arch/x86/include/asm/pmem.h +++ b/arch/x86/include/asm/pmem.h @@ -55,7 +55,8 @@ static inline int arch_memcpy_from_pmem(void *dst, const void *src, size_t n) * @size: number of bytes to write back * * Write back a cache range using the CLWB (cache line write back) - * instruction. + * instruction. Note that @size is internally rounded up to be cache + * line size aligned. */ static inline void arch_wb_cache_pmem(void *addr, size_t size) { @@ -69,15 +70,6 @@ static inline void arch_wb_cache_pmem(void *addr, size_t size) clwb(p); } -/* - * copy_from_iter_nocache() on x86 only uses non-temporal stores for iovec - * iterators, so for other types (bvec & kvec) we must do a cache write-back. - */ -static inline bool __iter_needs_pmem_wb(struct iov_iter *i) -{ - return iter_is_iovec(i) == false; -} - /** * arch_copy_from_iter_pmem - copy data from an iterator to PMEM * @addr: PMEM destination address @@ -94,7 +86,35 @@ static inline size_t arch_copy_from_iter_pmem(void *addr, size_t bytes, /* TODO: skip the write-back by always using non-temporal stores */ len = copy_from_iter_nocache(addr, bytes, i); - if (__iter_needs_pmem_wb(i)) + /* + * In the iovec case on x86_64 copy_from_iter_nocache() uses + * non-temporal stores for the bulk of the transfer, but we need + * to manually flush if the transfer is unaligned. A cached + * memory copy is used when destination or size is not naturally + * aligned. That is: + * - Require 8-byte alignment when size is 8 bytes or larger. + * - Require 4-byte alignment when size is 4 bytes. + * + * In the non-iovec case the entire destination needs to be + * flushed. + */ + if (iter_is_iovec(i)) { + unsigned long flushed, dest = (unsigned long) addr; + + if (bytes < 8) { + if (!IS_ALIGNED(dest, 4) || (bytes != 4)) + arch_wb_cache_pmem(addr, 1); + } else { + if (!IS_ALIGNED(dest, 8)) { + dest = ALIGN(dest, boot_cpu_data.x86_clflush_size); + arch_wb_cache_pmem(addr, 1); + } + + flushed = dest - (unsigned long) addr; + if (bytes > flushed && !IS_ALIGNED(bytes - flushed, 8)) + arch_wb_cache_pmem(addr + bytes - 1, 1); + } + } else arch_wb_cache_pmem(addr, bytes); return len; diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index f385eca5407a..3cada998a402 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -80,7 +80,7 @@ extern u16 __read_mostly tlb_lld_1g[NR_INFO]; /* * CPU type and hardware bug flags. Kept separately for each CPU. - * Members of this structure are referenced in head.S, so think twice + * Members of this structure are referenced in head_32.S, so think twice * before touching them. [mj] */ @@ -89,14 +89,7 @@ struct cpuinfo_x86 { __u8 x86_vendor; /* CPU vendor */ __u8 x86_model; __u8 x86_mask; -#ifdef CONFIG_X86_32 - char wp_works_ok; /* It doesn't on 386's */ - - /* Problems on some 486Dx4's and old 386's: */ - char rfu; - char pad0; - char pad1; -#else +#ifdef CONFIG_X86_64 /* Number of 4K pages in DTLB/ITLB combined(in pages): */ int x86_tlbsize; #endif @@ -716,6 +709,8 @@ extern struct desc_ptr early_gdt_descr; extern void cpu_set_gdt(int); extern void switch_to_new_gdt(int); +extern void load_direct_gdt(int); +extern void load_fixmap_gdt(int); extern void load_percpu_segment(int); extern void cpu_init(void); @@ -797,6 +792,7 @@ static inline void spin_lock_prefetch(const void *x) /* * User space process size: 3GB (default). */ +#define IA32_PAGE_OFFSET PAGE_OFFSET #define TASK_SIZE PAGE_OFFSET #define TASK_SIZE_MAX TASK_SIZE #define STACK_TOP TASK_SIZE @@ -873,7 +869,8 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) +#define __TASK_UNMAPPED_BASE(task_size) (PAGE_ALIGN(task_size / 3)) +#define TASK_UNMAPPED_BASE __TASK_UNMAPPED_BASE(TASK_SIZE) #define KSTK_EIP(task) (task_pt_regs(task)->ip) @@ -884,6 +881,8 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, extern int get_tsc_mode(unsigned long adr); extern int set_tsc_mode(unsigned int val); +DECLARE_PER_CPU(u64, msr_misc_features_shadow); + /* Register/unregister a process' MPX related resource */ #define MPX_ENABLE_MANAGEMENT() mpx_enable_management() #define MPX_DISABLE_MANAGEMENT() mpx_disable_management() diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index 9b9b30b19441..8d3964fc5f91 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h @@ -9,6 +9,7 @@ void syscall_init(void); #ifdef CONFIG_X86_64 void entry_SYSCALL_64(void); +long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2); #endif #ifdef CONFIG_X86_32 @@ -30,6 +31,7 @@ void x86_report_nx(void); extern int reboot_force; -long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); +long do_arch_prctl_common(struct task_struct *task, int option, + unsigned long cpuid_enabled); #endif /* _ASM_X86_PROTO_H */ diff --git a/arch/x86/include/asm/purgatory.h b/arch/x86/include/asm/purgatory.h new file mode 100644 index 000000000000..d7da2729903d --- /dev/null +++ b/arch/x86/include/asm/purgatory.h @@ -0,0 +1,20 @@ +#ifndef _ASM_X86_PURGATORY_H +#define _ASM_X86_PURGATORY_H + +#ifndef __ASSEMBLY__ +#include <linux/purgatory.h> + +extern void purgatory(void); +/* + * These forward declarations serve two purposes: + * + * 1) Make sparse happy when checking arch/purgatory + * 2) Document that these are required to be global so the symbol + * lookup in kexec works + */ +extern unsigned long purgatory_backup_dest; +extern unsigned long purgatory_backup_src; +extern unsigned long purgatory_backup_sz; +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_PURGATORY_H */ diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index 2cb1cc253d51..fc62ba8dce93 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h @@ -15,6 +15,7 @@ struct machine_ops { }; extern struct machine_ops machine_ops; +extern int crashing_cpu; void native_machine_crash_shutdown(struct pt_regs *regs); void native_machine_shutdown(void); diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h index fac9a5c0abe9..d91ba04dd007 100644 --- a/arch/x86/include/asm/required-features.h +++ b/arch/x86/include/asm/required-features.h @@ -53,6 +53,12 @@ # define NEED_MOVBE 0 #endif +#ifdef CONFIG_X86_5LEVEL +# define NEED_LA57 (1<<(X86_FEATURE_LA57 & 31)) +#else +# define NEED_LA57 0 +#endif + #ifdef CONFIG_X86_64 #ifdef CONFIG_PARAVIRT /* Paravirtualized systems may not have PSE or PGE available */ @@ -98,7 +104,7 @@ #define REQUIRED_MASK13 0 #define REQUIRED_MASK14 0 #define REQUIRED_MASK15 0 -#define REQUIRED_MASK16 0 +#define REQUIRED_MASK16 (NEED_LA57) #define REQUIRED_MASK17 0 #define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 026ea82ecc60..47103eca3775 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -149,6 +149,19 @@ void smp_store_cpu_info(int id); #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) #define cpu_acpi_id(cpu) per_cpu(x86_cpu_to_acpiid, cpu) +/* + * This function is needed by all SMP systems. It must _always_ be valid + * from the initial startup. We map APIC_BASE very early in page_setup(), + * so this is correct in the x86 case. + */ +#define raw_smp_processor_id() (this_cpu_read(cpu_number)) + +#ifdef CONFIG_X86_32 +extern int safe_smp_processor_id(void); +#else +# define safe_smp_processor_id() smp_processor_id() +#endif + #else /* !CONFIG_SMP */ #define wbinvd_on_cpu(cpu) wbinvd() static inline int wbinvd_on_all_cpus(void) @@ -161,22 +174,6 @@ static inline int wbinvd_on_all_cpus(void) extern unsigned disabled_cpus; -#ifdef CONFIG_X86_32_SMP -/* - * This function is needed by all SMP systems. It must _always_ be valid - * from the initial startup. We map APIC_BASE very early in page_setup(), - * so this is correct in the x86 case. - */ -#define raw_smp_processor_id() (this_cpu_read(cpu_number)) -extern int safe_smp_processor_id(void); - -#elif defined(CONFIG_X86_64_SMP) -#define raw_smp_processor_id() (this_cpu_read(cpu_number)) - -#define safe_smp_processor_id() smp_processor_id() - -#endif - #ifdef CONFIG_X86_LOCAL_APIC #ifndef CONFIG_X86_64 @@ -191,11 +188,7 @@ static inline int logical_smp_processor_id(void) extern int hard_smp_processor_id(void); #else /* CONFIG_X86_LOCAL_APIC */ - -# ifndef CONFIG_SMP -# define hard_smp_processor_id() 0 -# endif - +#define hard_smp_processor_id() 0 #endif /* CONFIG_X86_LOCAL_APIC */ #ifdef CONFIG_DEBUG_NMI_SELFTEST diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h index 4517d6b93188..1f5bee2c202f 100644 --- a/arch/x86/include/asm/sparsemem.h +++ b/arch/x86/include/asm/sparsemem.h @@ -26,8 +26,13 @@ # endif #else /* CONFIG_X86_32 */ # define SECTION_SIZE_BITS 27 /* matt - 128 is convenient right now */ -# define MAX_PHYSADDR_BITS 44 -# define MAX_PHYSMEM_BITS 46 +# ifdef CONFIG_X86_5LEVEL +# define MAX_PHYSADDR_BITS 52 +# define MAX_PHYSMEM_BITS 52 +# else +# define MAX_PHYSADDR_BITS 44 +# define MAX_PHYSMEM_BITS 46 +# endif #endif #endif /* CONFIG_SPARSEMEM */ diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index 58505f01962f..dcbd9bcce714 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -87,7 +87,7 @@ static inline void setup_stack_canary_segment(int cpu) { #ifdef CONFIG_X86_32 unsigned long canary = (unsigned long)&per_cpu(stack_canary, cpu); - struct desc_struct *gdt_table = get_cpu_gdt_table(cpu); + struct desc_struct *gdt_table = get_cpu_gdt_rw(cpu); struct desc_struct desc; desc = gdt_table[GDT_ENTRY_STACK_CANARY]; diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 83372dc43943..e00e1bd6e7b3 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -85,6 +85,7 @@ struct thread_info { #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ #define TIF_UPROBE 12 /* breakpointed or singlestepping */ #define TIF_PATCH_PENDING 13 /* pending live patching update */ +#define TIF_NOCPUID 15 /* CPUID is not accessible in userland */ #define TIF_NOTSC 16 /* TSC is not accessible in userland */ #define TIF_IA32 17 /* IA32 compatibility process */ #define TIF_NOHZ 19 /* in adaptive nohz mode */ @@ -109,6 +110,7 @@ struct thread_info { #define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) #define _TIF_UPROBE (1 << TIF_UPROBE) #define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING) +#define _TIF_NOCPUID (1 << TIF_NOCPUID) #define _TIF_NOTSC (1 << TIF_NOTSC) #define _TIF_IA32 (1 << TIF_IA32) #define _TIF_NOHZ (1 << TIF_NOHZ) @@ -139,7 +141,7 @@ struct thread_info { /* flags to check in __switch_to() */ #define _TIF_WORK_CTXSW \ - (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP) + (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP) #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW) @@ -169,9 +171,9 @@ static inline unsigned long current_stack_pointer(void) * entirely contained by a single stack frame. * * Returns: - * 1 if within a frame - * -1 if placed across a frame boundary (or outside stack) - * 0 unable to determine (no frame pointers, etc) + * GOOD_FRAME if within a frame + * BAD_STACK if placed across a frame boundary (or outside stack) + * NOT_STACK unable to determine (no frame pointers, etc) */ static inline int arch_within_stack_frames(const void * const stack, const void * const stackend, @@ -198,13 +200,14 @@ static inline int arch_within_stack_frames(const void * const stack, * the copy as invalid. */ if (obj + len <= frame) - return obj >= oldframe + 2 * sizeof(void *) ? 1 : -1; + return obj >= oldframe + 2 * sizeof(void *) ? + GOOD_FRAME : BAD_STACK; oldframe = frame; frame = *(const void * const *)frame; } - return -1; + return BAD_STACK; #else - return 0; + return NOT_STACK; #endif } @@ -240,6 +243,8 @@ static inline int arch_within_stack_frames(const void * const stack, extern void arch_task_cache_init(void); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); extern void arch_release_task_struct(struct task_struct *tsk); +extern void arch_setup_new_exec(void); +#define arch_setup_new_exec arch_setup_new_exec #endif /* !__ASSEMBLY__ */ #endif /* _ASM_X86_THREAD_INFO_H */ diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index a04eabd43d06..27e9f9d769b8 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h @@ -12,6 +12,8 @@ extern int recalibrate_cpu_khz(void); extern int no_timer_check; +extern bool using_native_sched_clock(void); + /* * We use the full linear equation: f(x) = a + b*x, in order to allow * a continuous function in the face of dynamic freq changes. diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 6fa85944af83..6ed9ea469b48 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -110,6 +110,16 @@ static inline void cr4_clear_bits(unsigned long mask) } } +static inline void cr4_toggle_bits(unsigned long mask) +{ + unsigned long cr4; + + cr4 = this_cpu_read(cpu_tlbstate.cr4); + cr4 ^= mask; + this_cpu_write(cpu_tlbstate.cr4, cr4); + __write_cr4(cr4); +} + /* Read the CR4 shadow. */ static inline unsigned long cr4_read_shadow(void) { @@ -188,7 +198,7 @@ static inline void __native_flush_tlb_single(unsigned long addr) static inline void __flush_tlb_all(void) { - if (static_cpu_has(X86_FEATURE_PGE)) + if (boot_cpu_has(X86_FEATURE_PGE)) __flush_tlb_global(); else __flush_tlb(); @@ -205,7 +215,6 @@ static inline void __flush_tlb_one(unsigned long addr) /* * TLB flushing: * - * - flush_tlb() flushes the current mm struct TLBs * - flush_tlb_all() flushes all processes TLBs * - flush_tlb_mm(mm) flushes the specified mm context TLB's * - flush_tlb_page(vma, vmaddr) flushes one page @@ -237,11 +246,6 @@ static inline void flush_tlb_all(void) __flush_tlb_all(); } -static inline void flush_tlb(void) -{ - __flush_tlb_up(); -} - static inline void local_flush_tlb(void) { __flush_tlb_up(); @@ -303,14 +307,11 @@ static inline void flush_tlb_kernel_range(unsigned long start, flush_tlb_mm_range(vma->vm_mm, start, end, vma->vm_flags) extern void flush_tlb_all(void); -extern void flush_tlb_current_task(void); extern void flush_tlb_page(struct vm_area_struct *, unsigned long); extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long vmflag); extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); -#define flush_tlb() flush_tlb_current_task() - void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long start, unsigned long end); diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index ea148313570f..68766b276d9e 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -3,19 +3,14 @@ /* * User space memory access functions */ -#include <linux/errno.h> #include <linux/compiler.h> #include <linux/kasan-checks.h> -#include <linux/thread_info.h> #include <linux/string.h> #include <asm/asm.h> #include <asm/page.h> #include <asm/smap.h> #include <asm/extable.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - /* * The fs value determines whether argument validity checking should be * performed or not. If get_fs() == USER_DS, checking is performed, with @@ -384,6 +379,18 @@ do { \ : "=r" (err), ltype(x) \ : "m" (__m(addr)), "i" (errret), "0" (err)) +#define __get_user_asm_nozero(x, addr, err, itype, rtype, ltype, errret) \ + asm volatile("\n" \ + "1: mov"itype" %2,%"rtype"1\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: mov %3,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + _ASM_EXTABLE(1b, 3b) \ + : "=r" (err), ltype(x) \ + : "m" (__m(addr)), "i" (errret), "0" (err)) + /* * This doesn't do __uaccess_begin/end - the exception handling * around it must do that. @@ -675,59 +682,6 @@ extern struct movsl_mask { # include <asm/uaccess_64.h> #endif -unsigned long __must_check _copy_from_user(void *to, const void __user *from, - unsigned n); -unsigned long __must_check _copy_to_user(void __user *to, const void *from, - unsigned n); - -extern void __compiletime_error("usercopy buffer size is too small") -__bad_copy_user(void); - -static inline void copy_user_overflow(int size, unsigned long count) -{ - WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); -} - -static __always_inline unsigned long __must_check -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - int sz = __compiletime_object_size(to); - - might_fault(); - - kasan_check_write(to, n); - - if (likely(sz < 0 || sz >= n)) { - check_object_size(to, n, false); - n = _copy_from_user(to, from, n); - } else if (!__builtin_constant_p(n)) - copy_user_overflow(sz, n); - else - __bad_copy_user(); - - return n; -} - -static __always_inline unsigned long __must_check -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - int sz = __compiletime_object_size(from); - - kasan_check_read(from, n); - - might_fault(); - - if (likely(sz < 0 || sz >= n)) { - check_object_size(from, n, true); - n = _copy_to_user(to, from, n); - } else if (!__builtin_constant_p(n)) - copy_user_overflow(sz, n); - else - __bad_copy_user(); - - return n; -} - /* * We rely on the nested NMI work to allow atomic faults from the NMI path; the * nested NMI paths are careful to preserve CR2. diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index 7d3bdd1ed697..aeda9bb8af50 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -4,149 +4,52 @@ /* * User space memory access functions */ -#include <linux/errno.h> -#include <linux/thread_info.h> #include <linux/string.h> #include <asm/asm.h> #include <asm/page.h> -unsigned long __must_check __copy_to_user_ll - (void __user *to, const void *from, unsigned long n); -unsigned long __must_check __copy_from_user_ll - (void *to, const void __user *from, unsigned long n); -unsigned long __must_check __copy_from_user_ll_nozero - (void *to, const void __user *from, unsigned long n); -unsigned long __must_check __copy_from_user_ll_nocache - (void *to, const void __user *from, unsigned long n); +unsigned long __must_check __copy_user_ll + (void *to, const void *from, unsigned long n); unsigned long __must_check __copy_from_user_ll_nocache_nozero (void *to, const void __user *from, unsigned long n); -/** - * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. - * - * Copy data from kernel space to user space. Caller must check - * the specified block with access_ok() before calling this function. - * The caller should also make sure he pins the user space address - * so that we don't result in page fault and sleep. - */ -static __always_inline unsigned long __must_check -__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) -{ - check_object_size(from, n, true); - return __copy_to_user_ll(to, from, n); -} - -/** - * __copy_to_user: - Copy a block of data into user space, with less checking. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ static __always_inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { - might_fault(); - return __copy_to_user_inatomic(to, from, n); + return __copy_user_ll((__force void *)to, from, n); } static __always_inline unsigned long -__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) -{ - return __copy_from_user_ll_nozero(to, from, n); -} - -/** - * __copy_from_user: - Copy a block of data from user space, with less checking. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - * - * An alternate version - __copy_from_user_inatomic() - may be called from - * atomic context and will fail rather than sleep. In this case the - * uncopied bytes will *NOT* be padded with zeros. See fs/filemap.h - * for explanation of why this is needed. - */ -static __always_inline unsigned long -__copy_from_user(void *to, const void __user *from, unsigned long n) -{ - might_fault(); - check_object_size(to, n, false); - if (__builtin_constant_p(n)) { - unsigned long ret; - - switch (n) { - case 1: - __uaccess_begin(); - __get_user_size(*(u8 *)to, from, 1, ret, 1); - __uaccess_end(); - return ret; - case 2: - __uaccess_begin(); - __get_user_size(*(u16 *)to, from, 2, ret, 2); - __uaccess_end(); - return ret; - case 4: - __uaccess_begin(); - __get_user_size(*(u32 *)to, from, 4, ret, 4); - __uaccess_end(); - return ret; - } - } - return __copy_from_user_ll(to, from, n); -} - -static __always_inline unsigned long __copy_from_user_nocache(void *to, - const void __user *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - might_fault(); if (__builtin_constant_p(n)) { unsigned long ret; switch (n) { case 1: + ret = 0; __uaccess_begin(); - __get_user_size(*(u8 *)to, from, 1, ret, 1); + __get_user_asm_nozero(*(u8 *)to, from, ret, + "b", "b", "=q", 1); __uaccess_end(); return ret; case 2: + ret = 0; __uaccess_begin(); - __get_user_size(*(u16 *)to, from, 2, ret, 2); + __get_user_asm_nozero(*(u16 *)to, from, ret, + "w", "w", "=r", 2); __uaccess_end(); return ret; case 4: + ret = 0; __uaccess_begin(); - __get_user_size(*(u32 *)to, from, 4, ret, 4); + __get_user_asm_nozero(*(u32 *)to, from, ret, + "l", "k", "=r", 4); __uaccess_end(); return ret; } } - return __copy_from_user_ll_nocache(to, from, n); + return __copy_user_ll(to, (__force const void *)from, n); } static __always_inline unsigned long diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 673059a109fe..c5504b9a472e 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -5,7 +5,6 @@ * User space memory access functions */ #include <linux/compiler.h> -#include <linux/errno.h> #include <linux/lockdep.h> #include <linux/kasan-checks.h> #include <asm/alternative.h> @@ -46,58 +45,54 @@ copy_user_generic(void *to, const void *from, unsigned len) return ret; } -__must_check unsigned long -copy_in_user(void __user *to, const void __user *from, unsigned len); - -static __always_inline __must_check -int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size) +static __always_inline __must_check unsigned long +raw_copy_from_user(void *dst, const void __user *src, unsigned long size) { int ret = 0; - check_object_size(dst, size, false); if (!__builtin_constant_p(size)) return copy_user_generic(dst, (__force void *)src, size); switch (size) { case 1: __uaccess_begin(); - __get_user_asm(*(u8 *)dst, (u8 __user *)src, + __get_user_asm_nozero(*(u8 *)dst, (u8 __user *)src, ret, "b", "b", "=q", 1); __uaccess_end(); return ret; case 2: __uaccess_begin(); - __get_user_asm(*(u16 *)dst, (u16 __user *)src, + __get_user_asm_nozero(*(u16 *)dst, (u16 __user *)src, ret, "w", "w", "=r", 2); __uaccess_end(); return ret; case 4: __uaccess_begin(); - __get_user_asm(*(u32 *)dst, (u32 __user *)src, + __get_user_asm_nozero(*(u32 *)dst, (u32 __user *)src, ret, "l", "k", "=r", 4); __uaccess_end(); return ret; case 8: __uaccess_begin(); - __get_user_asm(*(u64 *)dst, (u64 __user *)src, + __get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src, ret, "q", "", "=r", 8); __uaccess_end(); return ret; case 10: __uaccess_begin(); - __get_user_asm(*(u64 *)dst, (u64 __user *)src, + __get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src, ret, "q", "", "=r", 10); if (likely(!ret)) - __get_user_asm(*(u16 *)(8 + (char *)dst), + __get_user_asm_nozero(*(u16 *)(8 + (char *)dst), (u16 __user *)(8 + (char __user *)src), ret, "w", "w", "=r", 2); __uaccess_end(); return ret; case 16: __uaccess_begin(); - __get_user_asm(*(u64 *)dst, (u64 __user *)src, + __get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src, ret, "q", "", "=r", 16); if (likely(!ret)) - __get_user_asm(*(u64 *)(8 + (char *)dst), + __get_user_asm_nozero(*(u64 *)(8 + (char *)dst), (u64 __user *)(8 + (char __user *)src), ret, "q", "", "=r", 8); __uaccess_end(); @@ -107,20 +102,11 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size) } } -static __always_inline __must_check -int __copy_from_user(void *dst, const void __user *src, unsigned size) -{ - might_fault(); - kasan_check_write(dst, size); - return __copy_from_user_nocheck(dst, src, size); -} - -static __always_inline __must_check -int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size) +static __always_inline __must_check unsigned long +raw_copy_to_user(void __user *dst, const void *src, unsigned long size) { int ret = 0; - check_object_size(src, size, true); if (!__builtin_constant_p(size)) return copy_user_generic((__force void *)dst, src, size); switch (size) { @@ -176,100 +162,16 @@ int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size) } static __always_inline __must_check -int __copy_to_user(void __user *dst, const void *src, unsigned size) -{ - might_fault(); - kasan_check_read(src, size); - return __copy_to_user_nocheck(dst, src, size); -} - -static __always_inline __must_check -int __copy_in_user(void __user *dst, const void __user *src, unsigned size) -{ - int ret = 0; - - might_fault(); - if (!__builtin_constant_p(size)) - return copy_user_generic((__force void *)dst, - (__force void *)src, size); - switch (size) { - case 1: { - u8 tmp; - __uaccess_begin(); - __get_user_asm(tmp, (u8 __user *)src, - ret, "b", "b", "=q", 1); - if (likely(!ret)) - __put_user_asm(tmp, (u8 __user *)dst, - ret, "b", "b", "iq", 1); - __uaccess_end(); - return ret; - } - case 2: { - u16 tmp; - __uaccess_begin(); - __get_user_asm(tmp, (u16 __user *)src, - ret, "w", "w", "=r", 2); - if (likely(!ret)) - __put_user_asm(tmp, (u16 __user *)dst, - ret, "w", "w", "ir", 2); - __uaccess_end(); - return ret; - } - - case 4: { - u32 tmp; - __uaccess_begin(); - __get_user_asm(tmp, (u32 __user *)src, - ret, "l", "k", "=r", 4); - if (likely(!ret)) - __put_user_asm(tmp, (u32 __user *)dst, - ret, "l", "k", "ir", 4); - __uaccess_end(); - return ret; - } - case 8: { - u64 tmp; - __uaccess_begin(); - __get_user_asm(tmp, (u64 __user *)src, - ret, "q", "", "=r", 8); - if (likely(!ret)) - __put_user_asm(tmp, (u64 __user *)dst, - ret, "q", "", "er", 8); - __uaccess_end(); - return ret; - } - default: - return copy_user_generic((__force void *)dst, - (__force void *)src, size); - } -} - -static __must_check __always_inline int -__copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) -{ - kasan_check_write(dst, size); - return __copy_from_user_nocheck(dst, src, size); -} - -static __must_check __always_inline int -__copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) +unsigned long raw_copy_in_user(void __user *dst, const void __user *src, unsigned long size) { - kasan_check_read(src, size); - return __copy_to_user_nocheck(dst, src, size); + return copy_user_generic((__force void *)dst, + (__force void *)src, size); } extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size, int zerorest); static inline int -__copy_from_user_nocache(void *dst, const void __user *src, unsigned size) -{ - might_fault(); - kasan_check_write(dst, size); - return __copy_user_nocache(dst, src, size, 1); -} - -static inline int __copy_from_user_inatomic_nocache(void *dst, const void __user *src, unsigned size) { diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 32712a925f26..1ba1536f627e 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -23,7 +23,6 @@ # include <asm/unistd_64.h> # include <asm/unistd_64_x32.h> # define __ARCH_WANT_COMPAT_SYS_TIME -# define __ARCH_WANT_COMPAT_SYS_GETDENTS64 # define __ARCH_WANT_COMPAT_SYS_PREADV64 # define __ARCH_WANT_COMPAT_SYS_PWRITEV64 # define __ARCH_WANT_COMPAT_SYS_PREADV64V2 diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h index 137e9cce2ab4..e6676495b125 100644 --- a/arch/x86/include/asm/unwind.h +++ b/arch/x86/include/asm/unwind.h @@ -13,8 +13,10 @@ struct unwind_state { int graph_idx; bool error; #ifdef CONFIG_FRAME_POINTER + bool got_irq; unsigned long *bp, *orig_sp; struct pt_regs *regs; + unsigned long ip; #else unsigned long *sp; #endif diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 57ab86d94d64..7cac79802ad2 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -185,6 +185,15 @@ #define MSG_REGULAR 1 #define MSG_RETRY 2 +#define BAU_DESC_QUALIFIER 0x534749 + +enum uv_bau_version { + UV_BAU_V1 = 1, + UV_BAU_V2, + UV_BAU_V3, + UV_BAU_V4, +}; + /* * Distribution: 32 bytes (256 bits) (bytes 0-0x1f of descriptor) * If the 'multilevel' flag in the header portion of the descriptor @@ -222,20 +231,32 @@ struct bau_local_cpumask { * the s/w ack bit vector ] */ -/* - * The payload is software-defined for INTD transactions +/** + * struct uv1_2_3_bau_msg_payload - defines payload for INTD transactions + * @address: Signifies a page or all TLB's of the cpu + * @sending_cpu: CPU from which the message originates + * @acknowledge_count: CPUs on the destination Hub that received the interrupt */ -struct bau_msg_payload { - unsigned long address; /* signifies a page or all - TLB's of the cpu */ - /* 64 bits */ - unsigned short sending_cpu; /* filled in by sender */ - /* 16 bits */ - unsigned short acknowledge_count; /* filled in by destination */ - /* 16 bits */ - unsigned int reserved1:32; /* not usable */ +struct uv1_2_3_bau_msg_payload { + u64 address; + u16 sending_cpu; + u16 acknowledge_count; }; +/** + * struct uv4_bau_msg_payload - defines payload for INTD transactions + * @address: Signifies a page or all TLB's of the cpu + * @sending_cpu: CPU from which the message originates + * @acknowledge_count: CPUs on the destination Hub that received the interrupt + * @qualifier: Set by source to verify origin of INTD broadcast + */ +struct uv4_bau_msg_payload { + u64 address; + u16 sending_cpu; + u16 acknowledge_count; + u32 reserved:8; + u32 qualifier:24; +}; /* * UV1 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor) @@ -385,17 +406,6 @@ struct uv2_3_bau_msg_header { /* bits 127:120 */ }; -/* Abstracted BAU functions */ -struct bau_operations { - unsigned long (*read_l_sw_ack)(void); - unsigned long (*read_g_sw_ack)(int pnode); - unsigned long (*bau_gpa_to_offset)(unsigned long vaddr); - void (*write_l_sw_ack)(unsigned long mmr); - void (*write_g_sw_ack)(int pnode, unsigned long mmr); - void (*write_payload_first)(int pnode, unsigned long mmr); - void (*write_payload_last)(int pnode, unsigned long mmr); -}; - /* * The activation descriptor: * The format of the message to send, plus all accompanying control @@ -411,7 +421,10 @@ struct bau_desc { struct uv2_3_bau_msg_header uv2_3_hdr; } header; - struct bau_msg_payload payload; + union bau_payload_header { + struct uv1_2_3_bau_msg_payload uv1_2_3; + struct uv4_bau_msg_payload uv4; + } payload; }; /* UV1: * -payload-- ---------header------ @@ -588,8 +601,12 @@ struct uvhub_desc { struct socket_desc socket[2]; }; -/* - * one per-cpu; to locate the software tables +/** + * struct bau_control + * @status_mmr: location of status mmr, determined by uvhub_cpu + * @status_index: index of ERR|BUSY bits in status mmr, determined by uvhub_cpu + * + * Per-cpu control struct containing CPU topology information and BAU tuneables. */ struct bau_control { struct bau_desc *descriptor_base; @@ -607,6 +624,8 @@ struct bau_control { int timeout_tries; int ipi_attempts; int conseccompletes; + u64 status_mmr; + int status_index; bool nobau; short baudisabled; short cpu; @@ -644,6 +663,19 @@ struct bau_control { struct hub_and_pnode *thp; }; +/* Abstracted BAU functions */ +struct bau_operations { + unsigned long (*read_l_sw_ack)(void); + unsigned long (*read_g_sw_ack)(int pnode); + unsigned long (*bau_gpa_to_offset)(unsigned long vaddr); + void (*write_l_sw_ack)(unsigned long mmr); + void (*write_g_sw_ack)(int pnode, unsigned long mmr); + void (*write_payload_first)(int pnode, unsigned long mmr); + void (*write_payload_last)(int pnode, unsigned long mmr); + int (*wait_completion)(struct bau_desc*, + struct bau_control*, long try); +}; + static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image) { write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image); diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index 72e8300b1e8a..9cffb44a3cf5 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h @@ -485,15 +485,17 @@ static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr) if (paddr < uv_hub_info->lowmem_remap_top) paddr |= uv_hub_info->lowmem_remap_base; - paddr |= uv_hub_info->gnode_upper; - if (m_val) + + if (m_val) { + paddr |= uv_hub_info->gnode_upper; paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) | ((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift); - else + } else { paddr |= uv_soc_phys_ram_to_nasid(paddr) << uv_hub_info->gpa_shift; + } return paddr; } diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index 2444189cbe28..bccdf4938ddf 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h @@ -20,6 +20,7 @@ struct vdso_image { long sym_vvar_page; long sym_hpet_page; long sym_pvclock_page; + long sym_hvclock_page; long sym_VDSO32_NOTE_MASK; long sym___kernel_sigreturn; long sym___kernel_rt_sigreturn; diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 33cbd3db97b9..8a5a02b1dfba 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -6,6 +6,7 @@ #include <linux/spinlock.h> #include <linux/pfn.h> #include <linux/mm.h> +#include <linux/device.h> #include <linux/uaccess.h> #include <asm/page.h> @@ -279,13 +280,17 @@ static inline pte_t __pte_ma(pteval_t x) #define pmd_val_ma(v) ((v).pmd) #ifdef __PAGETABLE_PUD_FOLDED -#define pud_val_ma(v) ((v).pgd.pgd) +#define pud_val_ma(v) ((v).p4d.pgd.pgd) #else #define pud_val_ma(v) ((v).pud) #endif #define __pmd_ma(x) ((pmd_t) { (x) } ) -#define pgd_val_ma(x) ((x).pgd) +#ifdef __PAGETABLE_P4D_FOLDED +#define p4d_val_ma(x) ((x).pgd.pgd) +#else +#define p4d_val_ma(x) ((x).p4d) +#endif void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid); diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index 5138dacf8bb8..ddef37b16af2 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -34,7 +34,6 @@ #include <linux/screen_info.h> #include <linux/apm_bios.h> #include <linux/edd.h> -#include <asm/e820.h> #include <asm/ist.h> #include <video/edid.h> @@ -58,7 +57,7 @@ struct setup_header { __u32 header; __u16 version; __u32 realmode_swtch; - __u16 start_sys; + __u16 start_sys_seg; __u16 kernel_version; __u8 type_of_loader; __u8 loadflags; @@ -111,6 +110,21 @@ struct efi_info { __u32 efi_memmap_hi; }; +/* + * This is the maximum number of entries in struct boot_params::e820_table + * (the zeropage), which is part of the x86 boot protocol ABI: + */ +#define E820_MAX_ENTRIES_ZEROPAGE 128 + +/* + * The E820 memory region entry of the boot protocol ABI: + */ +struct boot_e820_entry { + __u64 addr; + __u64 size; + __u32 type; +} __attribute__((packed)); + /* The so-called "zeropage" */ struct boot_params { struct screen_info screen_info; /* 0x000 */ @@ -153,7 +167,7 @@ struct boot_params { struct setup_header hdr; /* setup header */ /* 0x1f1 */ __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ - struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */ __u8 _pad8[48]; /* 0xcd0 */ struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */ __u8 _pad9[276]; /* 0xeec */ diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h index 835aa51c7f6e..c45765517092 100644 --- a/arch/x86/include/uapi/asm/prctl.h +++ b/arch/x86/include/uapi/asm/prctl.h @@ -1,10 +1,13 @@ #ifndef _ASM_X86_PRCTL_H #define _ASM_X86_PRCTL_H -#define ARCH_SET_GS 0x1001 -#define ARCH_SET_FS 0x1002 -#define ARCH_GET_FS 0x1003 -#define ARCH_GET_GS 0x1004 +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 + +#define ARCH_GET_CPUID 0x1011 +#define ARCH_SET_CPUID 0x1012 #define ARCH_MAP_VDSO_X32 0x2001 #define ARCH_MAP_VDSO_32 0x2002 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 84c00592d359..4b994232cb57 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -27,7 +27,7 @@ KASAN_SANITIZE_stacktrace.o := n OBJECT_FILES_NON_STANDARD_head_$(BITS).o := y OBJECT_FILES_NON_STANDARD_relocate_kernel_$(BITS).o := y -OBJECT_FILES_NON_STANDARD_mcount_$(BITS).o := y +OBJECT_FILES_NON_STANDARD_ftrace_$(BITS).o := y OBJECT_FILES_NON_STANDARD_test_nx.o := y # If instrumentation of this dir is enabled, boot hangs during first second. @@ -46,7 +46,7 @@ obj-$(CONFIG_MODIFY_LDT_SYSCALL) += ldt.o obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o obj-$(CONFIG_IRQ_WORK) += irq_work.o obj-y += probe_roms.o -obj-$(CONFIG_X86_64) += sys_x86_64.o mcount_64.o +obj-$(CONFIG_X86_64) += sys_x86_64.o obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o obj-$(CONFIG_SYSFS) += ksysfs.o obj-y += bootflag.o e820.o @@ -82,6 +82,7 @@ obj-y += apic/ obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_LIVEPATCH) += livepatch.o +obj-$(CONFIG_FUNCTION_TRACER) += ftrace_$(BITS).o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_X86_TSC) += trace_clock.o diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index ae32838cac5f..6bb680671088 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -37,6 +37,7 @@ #include <linux/pci.h> #include <linux/efi-bgrt.h> +#include <asm/e820/api.h> #include <asm/irqdomain.h> #include <asm/pci_x86.h> #include <asm/pgtable.h> @@ -179,10 +180,15 @@ static int acpi_register_lapic(int id, u32 acpiid, u8 enabled) return -EINVAL; } + if (!enabled) { + ++disabled_cpus; + return -EINVAL; + } + if (boot_cpu_physical_apicid != -1U) ver = boot_cpu_apic_version; - cpu = __generic_processor_info(id, ver, enabled); + cpu = generic_processor_info(id, ver); if (cpu >= 0) early_per_cpu(x86_cpu_to_acpiid, cpu) = acpiid; @@ -710,7 +716,7 @@ static void __init acpi_set_irq_model_ioapic(void) #ifdef CONFIG_ACPI_HOTPLUG_CPU #include <acpi/processor.h> -int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) +static int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) { #ifdef CONFIG_ACPI_NUMA int nid; @@ -1559,12 +1565,6 @@ int __init early_acpi_boot_init(void) return 0; } -static int __init acpi_parse_bgrt(struct acpi_table_header *table) -{ - efi_bgrt_init(table); - return 0; -} - int __init acpi_boot_init(void) { /* those are executed after early-quirks are executed */ @@ -1724,6 +1724,6 @@ int __acpi_release_global_lock(unsigned int *lock) void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size) { - e820_add_region(addr, size, E820_ACPI); - update_e820(); + e820__range_add(addr, size, E820_TYPE_ACPI); + e820__update_table_print(); } diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 48587335ede8..ed014814ea35 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -101,7 +101,7 @@ int x86_acpi_suspend_lowlevel(void) #ifdef CONFIG_SMP initial_stack = (unsigned long)temp_stack + sizeof(temp_stack); early_gdt_descr.address = - (unsigned long)get_cpu_gdt_table(smp_processor_id()); + (unsigned long)get_cpu_gdt_rw(smp_processor_id()); initial_gs = per_cpu_offset(smp_processor_id()); #endif initial_code = (unsigned long)wakeup_long64; diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 0a2bb1f62e72..ef2859f9fcce 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -21,7 +21,7 @@ #include <linux/pci.h> #include <linux/bitops.h> #include <linux/suspend.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/io.h> #include <asm/iommu.h> #include <asm/gart.h> @@ -306,13 +306,13 @@ void __init early_gart_iommu_check(void) fix = 1; if (gart_fix_e820 && !fix && aper_enabled) { - if (e820_any_mapped(aper_base, aper_base + aper_size, - E820_RAM)) { + if (e820__mapped_any(aper_base, aper_base + aper_size, + E820_TYPE_RAM)) { /* reserve it, so we can reuse it in second kernel */ pr_info("e820: reserve [mem %#010Lx-%#010Lx] for GART\n", aper_base, aper_base + aper_size - 1); - e820_add_region(aper_base, aper_size, E820_RESERVED); - update_e820(); + e820__range_add(aper_base, aper_size, E820_TYPE_RESERVED); + e820__update_table_print(); } } diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 4261b3282ad9..2d75faf743f2 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -731,8 +731,10 @@ static int __init calibrate_APIC_clock(void) TICK_NSEC, lapic_clockevent.shift); lapic_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); + lapic_clockevent.max_delta_ticks = 0x7FFFFF; lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); + lapic_clockevent.min_delta_ticks = 0xF; lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; return 0; } @@ -778,8 +780,10 @@ static int __init calibrate_APIC_clock(void) lapic_clockevent.shift); lapic_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, &lapic_clockevent); + lapic_clockevent.max_delta_ticks = 0x7FFFFFFF; lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); + lapic_clockevent.min_delta_ticks = 0xF; lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; @@ -1610,24 +1614,15 @@ static inline void try_to_enable_x2apic(int remap_mode) { } static inline void __x2apic_enable(void) { } #endif /* !CONFIG_X86_X2APIC */ -static int __init try_to_enable_IR(void) -{ -#ifdef CONFIG_X86_IO_APIC - if (!x2apic_enabled() && skip_ioapic_setup) { - pr_info("Not enabling interrupt remapping due to skipped IO-APIC setup\n"); - return -1; - } -#endif - return irq_remapping_enable(); -} - void __init enable_IR_x2apic(void) { unsigned long flags; int ret, ir_stat; - if (skip_ioapic_setup) + if (skip_ioapic_setup) { + pr_info("Not enabling interrupt remapping due to skipped IO-APIC setup\n"); return; + } ir_stat = irq_remapping_prepare(); if (ir_stat < 0 && !x2apic_supported()) @@ -1645,7 +1640,7 @@ void __init enable_IR_x2apic(void) /* If irq_remapping_prepare() succeeded, try to enable it */ if (ir_stat >= 0) - ir_stat = try_to_enable_IR(); + ir_stat = irq_remapping_enable(); /* ir_stat contains the remap mode or an error code */ try_to_enable_x2apic(ir_stat); @@ -1798,8 +1793,8 @@ void __init init_apic_mappings(void) apic_phys = mp_lapic_addr; /* - * acpi lapic path already maps that address in - * acpi_register_lapic_address() + * If the system has ACPI MADT tables or MP info, the LAPIC + * address is already registered. */ if (!acpi_lapic && !smp_found_config) register_lapic_address(apic_phys); @@ -2062,17 +2057,17 @@ static int allocate_logical_cpuid(int apicid) /* Allocate a new cpuid. */ if (nr_logical_cpuids >= nr_cpu_ids) { - WARN_ONCE(1, "Only %d processors supported." + WARN_ONCE(1, "APIC: NR_CPUS/possible_cpus limit of %i reached. " "Processor %d/0x%x and the rest are ignored.\n", - nr_cpu_ids - 1, nr_logical_cpuids, apicid); - return -1; + nr_cpu_ids, nr_logical_cpuids, apicid); + return -EINVAL; } cpuid_to_apicid[nr_logical_cpuids] = apicid; return nr_logical_cpuids++; } -int __generic_processor_info(int apicid, int version, bool enabled) +int generic_processor_info(int apicid, int version) { int cpu, max = nr_cpu_ids; bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, @@ -2130,11 +2125,9 @@ int __generic_processor_info(int apicid, int version, bool enabled) if (num_processors >= nr_cpu_ids) { int thiscpu = max + disabled_cpus; - if (enabled) { - pr_warning("APIC: NR_CPUS/possible_cpus limit of %i " - "reached. Processor %d/0x%x ignored.\n", - max, thiscpu, apicid); - } + pr_warning("APIC: NR_CPUS/possible_cpus limit of %i " + "reached. Processor %d/0x%x ignored.\n", + max, thiscpu, apicid); disabled_cpus++; return -EINVAL; @@ -2186,23 +2179,13 @@ int __generic_processor_info(int apicid, int version, bool enabled) apic->x86_32_early_logical_apicid(cpu); #endif set_cpu_possible(cpu, true); - - if (enabled) { - num_processors++; - physid_set(apicid, phys_cpu_present_map); - set_cpu_present(cpu, true); - } else { - disabled_cpus++; - } + physid_set(apicid, phys_cpu_present_map); + set_cpu_present(cpu, true); + num_processors++; return cpu; } -int generic_processor_info(int apicid, int version) -{ - return __generic_processor_info(apicid, version, true); -} - int hard_smp_processor_id(void) { return read_apic_id(); @@ -2258,7 +2241,7 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) static void __init apic_bsp_up_setup(void) { #ifdef CONFIG_X86_64 - apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); + apic_write(APIC_ID, apic->set_apic_id(boot_cpu_physical_apicid)); #else /* * Hack: In case of kdump, after a crash, kernel might be booting @@ -2648,7 +2631,7 @@ static int __init lapic_insert_resource(void) } /* - * need call insert after e820_reserve_resources() + * need call insert after e820__reserve_resources() * that is using request_resource */ late_initcall(lapic_insert_resource); diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index b109e4389c92..2262eb6df796 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -26,7 +26,7 @@ #include <linux/interrupt.h> #include <asm/acpi.h> -#include <asm/e820.h> +#include <asm/e820/api.h> static void noop_init_apic_ldr(void) { } static void noop_send_IPI(int cpu, int vector) { } diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index c48264e202fd..2e8f7f048f4f 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -25,7 +25,7 @@ #include <linux/interrupt.h> #include <asm/acpi.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index e9f8f8cdd570..b487b3a01615 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -34,6 +34,7 @@ #include <asm/uv/bios.h> #include <asm/uv/uv.h> #include <asm/apic.h> +#include <asm/e820/api.h> #include <asm/ipi.h> #include <asm/smp.h> #include <asm/x86_init.h> @@ -1105,7 +1106,8 @@ void __init uv_init_hub_info(struct uv_hub_info_s *hi) node_id.v = uv_read_local_mmr(UVH_NODE_ID); uv_cpuid.gnode_shift = max_t(unsigned int, uv_cpuid.gnode_shift, mn.n_val); hi->gnode_extra = (node_id.s.node_id & ~((1 << uv_cpuid.gnode_shift) - 1)) >> 1; - hi->gnode_upper = (unsigned long)hi->gnode_extra << mn.m_val; + if (mn.m_val) + hi->gnode_upper = (u64)hi->gnode_extra << mn.m_val; if (uv_gp_table) { hi->global_mmr_base = uv_gp_table->mmr_base; diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 5a414545e8a3..446b0d3d4932 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -609,7 +609,7 @@ static long __apm_bios_call(void *_call) cpu = get_cpu(); BUG_ON(cpu != 0); - gdt = get_cpu_gdt_table(cpu); + gdt = get_cpu_gdt_rw(cpu); save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; @@ -685,7 +685,7 @@ static long __apm_bios_call_simple(void *_call) cpu = get_cpu(); BUG_ON(cpu != 0); - gdt = get_cpu_gdt_table(cpu); + gdt = get_cpu_gdt_rw(cpu); save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; @@ -2352,7 +2352,7 @@ static int __init apm_init(void) * Note we only set APM segments on CPU zero, since we pin the APM * code to that CPU. */ - gdt = get_cpu_gdt_table(0); + gdt = get_cpu_gdt_rw(0); set_desc_base(&gdt[APM_CS >> 3], (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4)); set_desc_base(&gdt[APM_CS_16 >> 3], diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 35a5d5dca2fa..c36140d788fe 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -556,10 +556,6 @@ static void early_init_amd(struct cpuinfo_x86 *c) if (c->x86_power & (1 << 8)) { set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); - if (check_tsc_unstable()) - clear_sched_clock_stable(); - } else { - clear_sched_clock_stable(); } /* Bit 12 of 8000_0007 edx is accumulated power mechanism. */ diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index adc0ebd8bed0..44207b71fee1 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -3,7 +3,7 @@ #include <linux/sched/clock.h> #include <asm/cpufeature.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mtrr.h> #include <asm/msr.h> @@ -105,8 +105,6 @@ static void early_init_centaur(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_64 set_cpu_cap(c, X86_FEATURE_SYSENTER32); #endif - - clear_sched_clock_stable(); } static void init_centaur(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b11b38c3b0bd..8ee32119144d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -88,7 +88,6 @@ static void default_init(struct cpuinfo_x86 *c) strcpy(c->x86_model_id, "386"); } #endif - clear_sched_clock_stable(); } static const struct cpu_dev default_cpu = { @@ -449,19 +448,60 @@ void load_percpu_segment(int cpu) load_stack_canary_segment(); } +/* Setup the fixmap mapping only once per-processor */ +static inline void setup_fixmap_gdt(int cpu) +{ +#ifdef CONFIG_X86_64 + /* On 64-bit systems, we use a read-only fixmap GDT. */ + pgprot_t prot = PAGE_KERNEL_RO; +#else + /* + * On native 32-bit systems, the GDT cannot be read-only because + * our double fault handler uses a task gate, and entering through + * a task gate needs to change an available TSS to busy. If the GDT + * is read-only, that will triple fault. + * + * On Xen PV, the GDT must be read-only because the hypervisor requires + * it. + */ + pgprot_t prot = boot_cpu_has(X86_FEATURE_XENPV) ? + PAGE_KERNEL_RO : PAGE_KERNEL; +#endif + + __set_fixmap(get_cpu_gdt_ro_index(cpu), get_cpu_gdt_paddr(cpu), prot); +} + +/* Load the original GDT from the per-cpu structure */ +void load_direct_gdt(int cpu) +{ + struct desc_ptr gdt_descr; + + gdt_descr.address = (long)get_cpu_gdt_rw(cpu); + gdt_descr.size = GDT_SIZE - 1; + load_gdt(&gdt_descr); +} +EXPORT_SYMBOL_GPL(load_direct_gdt); + +/* Load a fixmap remapping of the per-cpu GDT */ +void load_fixmap_gdt(int cpu) +{ + struct desc_ptr gdt_descr; + + gdt_descr.address = (long)get_cpu_gdt_ro(cpu); + gdt_descr.size = GDT_SIZE - 1; + load_gdt(&gdt_descr); +} +EXPORT_SYMBOL_GPL(load_fixmap_gdt); + /* * Current gdt points %fs at the "master" per-cpu area: after this, * it's on the real one. */ void switch_to_new_gdt(int cpu) { - struct desc_ptr gdt_descr; - - gdt_descr.address = (long)get_cpu_gdt_table(cpu); - gdt_descr.size = GDT_SIZE - 1; - load_gdt(&gdt_descr); + /* Load the original GDT */ + load_direct_gdt(cpu); /* Reload the per-cpu base */ - load_percpu_segment(cpu); } @@ -1077,8 +1117,6 @@ static void identify_cpu(struct cpuinfo_x86 *c) */ if (this_cpu->c_init) this_cpu->c_init(c); - else - clear_sched_clock_stable(); /* Disable the PN if appropriate */ squash_the_stupid_serial_number(c); @@ -1529,6 +1567,9 @@ void cpu_init(void) if (is_uv_system()) uv_cpu_init(); + + setup_fixmap_gdt(cpu); + load_fixmap_gdt(cpu); } #else @@ -1584,6 +1625,9 @@ void cpu_init(void) dbg_restore_debug_regs(); fpu__init_cpu(); + + setup_fixmap_gdt(cpu); + load_fixmap_gdt(cpu); } #endif diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 0a3bc19de017..a70fd61095f8 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -185,7 +185,6 @@ static void early_init_cyrix(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); break; } - clear_sched_clock_stable(); } static void init_cyrix(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index fe0a615a051b..dfa90a3a5145 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -90,16 +90,12 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c) return; } - if (ring3mwait_disabled) { - msr_clear_bit(MSR_MISC_FEATURE_ENABLES, - MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT); + if (ring3mwait_disabled) return; - } - - msr_set_bit(MSR_MISC_FEATURE_ENABLES, - MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT); set_cpu_cap(c, X86_FEATURE_RING3MWAIT); + this_cpu_or(msr_misc_features_shadow, + 1UL << MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT); if (c == &boot_cpu_data) ELF_HWCAP2 |= HWCAP2_RING3MWAIT; @@ -162,10 +158,6 @@ static void early_init_intel(struct cpuinfo_x86 *c) if (c->x86_power & (1 << 8)) { set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); - if (check_tsc_unstable()) - clear_sched_clock_stable(); - } else { - clear_sched_clock_stable(); } /* Penwell and Cloverview have the TSC which doesn't sleep on S3 */ @@ -492,6 +484,34 @@ static void intel_bsp_resume(struct cpuinfo_x86 *c) init_intel_energy_perf(c); } +static void init_cpuid_fault(struct cpuinfo_x86 *c) +{ + u64 msr; + + if (!rdmsrl_safe(MSR_PLATFORM_INFO, &msr)) { + if (msr & MSR_PLATFORM_INFO_CPUID_FAULT) + set_cpu_cap(c, X86_FEATURE_CPUID_FAULT); + } +} + +static void init_intel_misc_features(struct cpuinfo_x86 *c) +{ + u64 msr; + + if (rdmsrl_safe(MSR_MISC_FEATURES_ENABLES, &msr)) + return; + + /* Clear all MISC features */ + this_cpu_write(msr_misc_features_shadow, 0); + + /* Check features and update capabilities and shadow control bits */ + init_cpuid_fault(c); + probe_xeon_phi_r3mwait(c); + + msr = this_cpu_read(msr_misc_features_shadow); + wrmsrl(MSR_MISC_FEATURES_ENABLES, msr); +} + static void init_intel(struct cpuinfo_x86 *c) { unsigned int l2 = 0; @@ -606,7 +626,7 @@ static void init_intel(struct cpuinfo_x86 *c) init_intel_energy_perf(c); - probe_xeon_phi_r3mwait(c); + init_intel_misc_features(c); } #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 5a533fefefa0..5b366462f579 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -32,55 +32,98 @@ #include <asm/intel-family.h> #include <asm/intel_rdt.h> +#define MAX_MBA_BW 100u +#define MBA_IS_LINEAR 0x4 + /* Mutex to protect rdtgroup access. */ DEFINE_MUTEX(rdtgroup_mutex); DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); +/* + * Used to store the max resource name width and max resource data width + * to display the schemata in a tabular format + */ +int max_name_width, max_data_width; + +static void +mba_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r); +static void +cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r); + #define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains) struct rdt_resource rdt_resources_all[] = { { - .name = "L3", - .domains = domain_init(RDT_RESOURCE_L3), - .msr_base = IA32_L3_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 3, - .cbm_idx_multi = 1, - .cbm_idx_offset = 0 + .name = "L3", + .domains = domain_init(RDT_RESOURCE_L3), + .msr_base = IA32_L3_CBM_BASE, + .msr_update = cat_wrmsr, + .cache_level = 3, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 1, + .cbm_idx_offset = 0, + }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", + }, + { + .name = "L3DATA", + .domains = domain_init(RDT_RESOURCE_L3DATA), + .msr_base = IA32_L3_CBM_BASE, + .msr_update = cat_wrmsr, + .cache_level = 3, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 2, + .cbm_idx_offset = 0, + }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { - .name = "L3DATA", - .domains = domain_init(RDT_RESOURCE_L3DATA), - .msr_base = IA32_L3_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 3, - .cbm_idx_multi = 2, - .cbm_idx_offset = 0 + .name = "L3CODE", + .domains = domain_init(RDT_RESOURCE_L3CODE), + .msr_base = IA32_L3_CBM_BASE, + .msr_update = cat_wrmsr, + .cache_level = 3, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 2, + .cbm_idx_offset = 1, + }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { - .name = "L3CODE", - .domains = domain_init(RDT_RESOURCE_L3CODE), - .msr_base = IA32_L3_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 3, - .cbm_idx_multi = 2, - .cbm_idx_offset = 1 + .name = "L2", + .domains = domain_init(RDT_RESOURCE_L2), + .msr_base = IA32_L2_CBM_BASE, + .msr_update = cat_wrmsr, + .cache_level = 2, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 1, + .cbm_idx_offset = 0, + }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { - .name = "L2", - .domains = domain_init(RDT_RESOURCE_L2), - .msr_base = IA32_L2_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 2, - .cbm_idx_multi = 1, - .cbm_idx_offset = 0 + .name = "MB", + .domains = domain_init(RDT_RESOURCE_MBA), + .msr_base = IA32_MBA_THRTL_BASE, + .msr_update = mba_wrmsr, + .cache_level = 3, + .parse_ctrlval = parse_bw, + .format_str = "%d=%*d", }, }; -static int cbm_idx(struct rdt_resource *r, int closid) +static unsigned int cbm_idx(struct rdt_resource *r, unsigned int closid) { - return closid * r->cbm_idx_multi + r->cbm_idx_offset; + return closid * r->cache.cbm_idx_mult + r->cache.cbm_idx_offset; } /* @@ -118,9 +161,9 @@ static inline bool cache_alloc_hsw_probe(void) return false; r->num_closid = 4; - r->cbm_len = 20; - r->max_cbm = max_cbm; - r->min_cbm_bits = 2; + r->default_ctrl = max_cbm; + r->cache.cbm_len = 20; + r->cache.min_cbm_bits = 2; r->capable = true; r->enabled = true; @@ -130,16 +173,66 @@ static inline bool cache_alloc_hsw_probe(void) return false; } -static void rdt_get_config(int idx, struct rdt_resource *r) +/* + * rdt_get_mb_table() - get a mapping of bandwidth(b/w) percentage values + * exposed to user interface and the h/w understandable delay values. + * + * The non-linear delay values have the granularity of power of two + * and also the h/w does not guarantee a curve for configured delay + * values vs. actual b/w enforced. + * Hence we need a mapping that is pre calibrated so the user can + * express the memory b/w as a percentage value. + */ +static inline bool rdt_get_mb_table(struct rdt_resource *r) +{ + /* + * There are no Intel SKUs as of now to support non-linear delay. + */ + pr_info("MBA b/w map not implemented for cpu:%d, model:%d", + boot_cpu_data.x86, boot_cpu_data.x86_model); + + return false; +} + +static bool rdt_get_mem_config(struct rdt_resource *r) +{ + union cpuid_0x10_3_eax eax; + union cpuid_0x10_x_edx edx; + u32 ebx, ecx; + + cpuid_count(0x00000010, 3, &eax.full, &ebx, &ecx, &edx.full); + r->num_closid = edx.split.cos_max + 1; + r->membw.max_delay = eax.split.max_delay + 1; + r->default_ctrl = MAX_MBA_BW; + if (ecx & MBA_IS_LINEAR) { + r->membw.delay_linear = true; + r->membw.min_bw = MAX_MBA_BW - r->membw.max_delay; + r->membw.bw_gran = MAX_MBA_BW - r->membw.max_delay; + } else { + if (!rdt_get_mb_table(r)) + return false; + } + r->data_width = 3; + rdt_get_mba_infofile(r); + + r->capable = true; + r->enabled = true; + + return true; +} + +static void rdt_get_cache_config(int idx, struct rdt_resource *r) { union cpuid_0x10_1_eax eax; - union cpuid_0x10_1_edx edx; + union cpuid_0x10_x_edx edx; u32 ebx, ecx; cpuid_count(0x00000010, idx, &eax.full, &ebx, &ecx, &edx.full); r->num_closid = edx.split.cos_max + 1; - r->cbm_len = eax.split.cbm_len + 1; - r->max_cbm = BIT_MASK(eax.split.cbm_len + 1) - 1; + r->cache.cbm_len = eax.split.cbm_len + 1; + r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1; + r->data_width = (r->cache.cbm_len + 3) / 4; + rdt_get_cache_infofile(r); r->capable = true; r->enabled = true; } @@ -150,8 +243,9 @@ static void rdt_get_cdp_l3_config(int type) struct rdt_resource *r = &rdt_resources_all[type]; r->num_closid = r_l3->num_closid / 2; - r->cbm_len = r_l3->cbm_len; - r->max_cbm = r_l3->max_cbm; + r->cache.cbm_len = r_l3->cache.cbm_len; + r->default_ctrl = r_l3->default_ctrl; + r->data_width = (r->cache.cbm_len + 3) / 4; r->capable = true; /* * By default, CDP is disabled. CDP can be enabled by mount parameter @@ -160,33 +254,6 @@ static void rdt_get_cdp_l3_config(int type) r->enabled = false; } -static inline bool get_rdt_resources(void) -{ - bool ret = false; - - if (cache_alloc_hsw_probe()) - return true; - - if (!boot_cpu_has(X86_FEATURE_RDT_A)) - return false; - - if (boot_cpu_has(X86_FEATURE_CAT_L3)) { - rdt_get_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); - if (boot_cpu_has(X86_FEATURE_CDP_L3)) { - rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA); - rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE); - } - ret = true; - } - if (boot_cpu_has(X86_FEATURE_CAT_L2)) { - /* CPUID 0x10.2 fields are same format at 0x10.1 */ - rdt_get_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); - ret = true; - } - - return ret; -} - static int get_cache_id(int cpu, int level) { struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu); @@ -200,29 +267,55 @@ static int get_cache_id(int cpu, int level) return -1; } -void rdt_cbm_update(void *arg) +/* + * Map the memory b/w percentage value to delay values + * that can be written to QOS_MSRs. + * There are currently no SKUs which support non linear delay values. + */ +static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r) { - struct msr_param *m = (struct msr_param *)arg; + if (r->membw.delay_linear) + return MAX_MBA_BW - bw; + + pr_warn_once("Non Linear delay-bw map not supported but queried\n"); + return r->default_ctrl; +} + +static void +mba_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r) +{ + unsigned int i; + + /* Write the delay values for mba. */ + for (i = m->low; i < m->high; i++) + wrmsrl(r->msr_base + i, delay_bw_map(d->ctrl_val[i], r)); +} + +static void +cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r) +{ + unsigned int i; + + for (i = m->low; i < m->high; i++) + wrmsrl(r->msr_base + cbm_idx(r, i), d->ctrl_val[i]); +} + +void rdt_ctrl_update(void *arg) +{ + struct msr_param *m = arg; struct rdt_resource *r = m->res; - int i, cpu = smp_processor_id(); + int cpu = smp_processor_id(); struct rdt_domain *d; list_for_each_entry(d, &r->domains, list) { /* Find the domain that contains this CPU */ - if (cpumask_test_cpu(cpu, &d->cpu_mask)) - goto found; + if (cpumask_test_cpu(cpu, &d->cpu_mask)) { + r->msr_update(d, m, r); + return; + } } - pr_info_once("cpu %d not found in any domain for resource %s\n", + pr_warn_once("cpu %d not found in any domain for resource %s\n", cpu, r->name); - - return; - -found: - for (i = m->low; i < m->high; i++) { - int idx = cbm_idx(r, i); - - wrmsrl(r->msr_base + idx, d->cbm[i]); - } } /* @@ -258,6 +351,32 @@ static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id, return NULL; } +static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d) +{ + struct msr_param m; + u32 *dc; + int i; + + dc = kmalloc_array(r->num_closid, sizeof(*d->ctrl_val), GFP_KERNEL); + if (!dc) + return -ENOMEM; + + d->ctrl_val = dc; + + /* + * Initialize the Control MSRs to having no control. + * For Cache Allocation: Set all bits in cbm + * For Memory Allocation: Set b/w requested to 100 + */ + for (i = 0; i < r->num_closid; i++, dc++) + *dc = r->default_ctrl; + + m.low = 0; + m.high = r->num_closid; + r->msr_update(d, &m, r); + return 0; +} + /* * domain_add_cpu - Add a cpu to a resource's domain list. * @@ -273,7 +392,7 @@ static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id, */ static void domain_add_cpu(int cpu, struct rdt_resource *r) { - int i, id = get_cache_id(cpu, r->cache_level); + int id = get_cache_id(cpu, r->cache_level); struct list_head *add_pos = NULL; struct rdt_domain *d; @@ -294,22 +413,13 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) d->id = id; - d->cbm = kmalloc_array(r->num_closid, sizeof(*d->cbm), GFP_KERNEL); - if (!d->cbm) { + if (domain_setup_ctrlval(r, d)) { kfree(d); return; } - for (i = 0; i < r->num_closid; i++) { - int idx = cbm_idx(r, i); - - d->cbm[i] = r->max_cbm; - wrmsrl(r->msr_base + idx, d->cbm[i]); - } - cpumask_set_cpu(cpu, &d->cpu_mask); list_add_tail(&d->list, add_pos); - r->num_domains++; } static void domain_remove_cpu(int cpu, struct rdt_resource *r) @@ -325,8 +435,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) cpumask_clear_cpu(cpu, &d->cpu_mask); if (cpumask_empty(&d->cpu_mask)) { - r->num_domains--; - kfree(d->cbm); + kfree(d->ctrl_val); list_del(&d->list); kfree(d); } @@ -374,6 +483,57 @@ static int intel_rdt_offline_cpu(unsigned int cpu) return 0; } +/* + * Choose a width for the resource name and resource data based on the + * resource that has widest name and cbm. + */ +static __init void rdt_init_padding(void) +{ + struct rdt_resource *r; + int cl; + + for_each_capable_rdt_resource(r) { + cl = strlen(r->name); + if (cl > max_name_width) + max_name_width = cl; + + if (r->data_width > max_data_width) + max_data_width = r->data_width; + } +} + +static __init bool get_rdt_resources(void) +{ + bool ret = false; + + if (cache_alloc_hsw_probe()) + return true; + + if (!boot_cpu_has(X86_FEATURE_RDT_A)) + return false; + + if (boot_cpu_has(X86_FEATURE_CAT_L3)) { + rdt_get_cache_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); + if (boot_cpu_has(X86_FEATURE_CDP_L3)) { + rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA); + rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE); + } + ret = true; + } + if (boot_cpu_has(X86_FEATURE_CAT_L2)) { + /* CPUID 0x10.2 fields are same format at 0x10.1 */ + rdt_get_cache_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); + ret = true; + } + + if (boot_cpu_has(X86_FEATURE_MBA)) { + if (rdt_get_mem_config(&rdt_resources_all[RDT_RESOURCE_MBA])) + ret = true; + } + + return ret; +} + static int __init intel_rdt_late_init(void) { struct rdt_resource *r; @@ -382,6 +542,8 @@ static int __init intel_rdt_late_init(void) if (!get_rdt_resources()) return -ENODEV; + rdt_init_padding(); + state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/rdt/cat:online:", intel_rdt_online_cpu, intel_rdt_offline_cpu); diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 0bbe0f3a039f..f5af0cc7eb0d 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -28,7 +28,6 @@ #include <linux/sched/signal.h> #include <linux/sched/task.h> #include <linux/slab.h> -#include <linux/cpu.h> #include <linux/task_work.h> #include <uapi/linux/magic.h> @@ -175,6 +174,13 @@ static struct kernfs_ops rdtgroup_kf_single_ops = { .seq_show = rdtgroup_seqfile_show, }; +static bool is_cpu_list(struct kernfs_open_file *of) +{ + struct rftype *rft = of->kn->priv; + + return rft->flags & RFTYPE_FLAGS_CPUS_LIST; +} + static int rdtgroup_cpus_show(struct kernfs_open_file *of, struct seq_file *s, void *v) { @@ -183,10 +189,12 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of, rdtgrp = rdtgroup_kn_lock_live(of->kn); - if (rdtgrp) - seq_printf(s, "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask)); - else + if (rdtgrp) { + seq_printf(s, is_cpu_list(of) ? "%*pbl\n" : "%*pb\n", + cpumask_pr_args(&rdtgrp->cpu_mask)); + } else { ret = -ENOENT; + } rdtgroup_kn_unlock(of->kn); return ret; @@ -253,7 +261,11 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of, goto unlock; } - ret = cpumask_parse(buf, newmask); + if (is_cpu_list(of)) + ret = cpulist_parse(buf, newmask); + else + ret = cpumask_parse(buf, newmask); + if (ret) goto unlock; @@ -474,6 +486,14 @@ static struct rftype rdtgroup_base_files[] = { .seq_show = rdtgroup_cpus_show, }, { + .name = "cpus_list", + .mode = 0644, + .kf_ops = &rdtgroup_kf_single_ops, + .write = rdtgroup_cpus_write, + .seq_show = rdtgroup_cpus_show, + .flags = RFTYPE_FLAGS_CPUS_LIST, + }, + { .name = "tasks", .mode = 0644, .kf_ops = &rdtgroup_kf_single_ops, @@ -495,32 +515,56 @@ static int rdt_num_closids_show(struct kernfs_open_file *of, struct rdt_resource *r = of->kn->parent->priv; seq_printf(seq, "%d\n", r->num_closid); + return 0; +} +static int rdt_default_ctrl_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) +{ + struct rdt_resource *r = of->kn->parent->priv; + + seq_printf(seq, "%x\n", r->default_ctrl); return 0; } -static int rdt_cbm_mask_show(struct kernfs_open_file *of, +static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { struct rdt_resource *r = of->kn->parent->priv; - seq_printf(seq, "%x\n", r->max_cbm); + seq_printf(seq, "%u\n", r->cache.min_cbm_bits); + return 0; +} + +static int rdt_min_bw_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) +{ + struct rdt_resource *r = of->kn->parent->priv; + seq_printf(seq, "%u\n", r->membw.min_bw); return 0; } -static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, +static int rdt_bw_gran_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { struct rdt_resource *r = of->kn->parent->priv; - seq_printf(seq, "%d\n", r->min_cbm_bits); + seq_printf(seq, "%u\n", r->membw.bw_gran); + return 0; +} +static int rdt_delay_linear_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) +{ + struct rdt_resource *r = of->kn->parent->priv; + + seq_printf(seq, "%u\n", r->membw.delay_linear); return 0; } /* rdtgroup information files for one cache resource. */ -static struct rftype res_info_files[] = { +static struct rftype res_cache_info_files[] = { { .name = "num_closids", .mode = 0444, @@ -531,7 +575,7 @@ static struct rftype res_info_files[] = { .name = "cbm_mask", .mode = 0444, .kf_ops = &rdtgroup_kf_single_ops, - .seq_show = rdt_cbm_mask_show, + .seq_show = rdt_default_ctrl_show, }, { .name = "min_cbm_bits", @@ -541,11 +585,52 @@ static struct rftype res_info_files[] = { }, }; +/* rdtgroup information files for memory bandwidth. */ +static struct rftype res_mba_info_files[] = { + { + .name = "num_closids", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_num_closids_show, + }, + { + .name = "min_bandwidth", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_min_bw_show, + }, + { + .name = "bandwidth_gran", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_bw_gran_show, + }, + { + .name = "delay_linear", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_delay_linear_show, + }, +}; + +void rdt_get_mba_infofile(struct rdt_resource *r) +{ + r->info_files = res_mba_info_files; + r->nr_info_files = ARRAY_SIZE(res_mba_info_files); +} + +void rdt_get_cache_infofile(struct rdt_resource *r) +{ + r->info_files = res_cache_info_files; + r->nr_info_files = ARRAY_SIZE(res_cache_info_files); +} + static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) { struct kernfs_node *kn_subdir; + struct rftype *res_info_files; struct rdt_resource *r; - int ret; + int ret, len; /* create the directory */ kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL); @@ -564,8 +649,11 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) ret = rdtgroup_kn_set_ugid(kn_subdir); if (ret) goto out_destroy; - ret = rdtgroup_add_files(kn_subdir, res_info_files, - ARRAY_SIZE(res_info_files)); + + res_info_files = r->info_files; + len = r->nr_info_files; + + ret = rdtgroup_add_files(kn_subdir, res_info_files, len); if (ret) goto out_destroy; kernfs_activate(kn_subdir); @@ -728,7 +816,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn) if (atomic_dec_and_test(&rdtgrp->waitcount) && (rdtgrp->flags & RDT_DELETED)) { kernfs_unbreak_active_protection(kn); - kernfs_put(kn); + kernfs_put(rdtgrp->kn); kfree(rdtgrp); } else { kernfs_unbreak_active_protection(kn); @@ -781,7 +869,7 @@ out: return dentry; } -static int reset_all_cbms(struct rdt_resource *r) +static int reset_all_ctrls(struct rdt_resource *r) { struct msr_param msr_param; cpumask_var_t cpu_mask; @@ -804,14 +892,14 @@ static int reset_all_cbms(struct rdt_resource *r) cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); for (i = 0; i < r->num_closid; i++) - d->cbm[i] = r->max_cbm; + d->ctrl_val[i] = r->default_ctrl; } cpu = get_cpu(); /* Update CBM on this cpu if it's in cpu_mask. */ if (cpumask_test_cpu(cpu, cpu_mask)) - rdt_cbm_update(&msr_param); + rdt_ctrl_update(&msr_param); /* Update CBM on all other cpus in cpu_mask. */ - smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1); + smp_call_function_many(cpu_mask, rdt_ctrl_update, &msr_param, 1); put_cpu(); free_cpumask_var(cpu_mask); @@ -897,7 +985,7 @@ static void rdt_kill_sb(struct super_block *sb) /*Put everything back to default values. */ for_each_enabled_rdt_resource(r) - reset_all_cbms(r); + reset_all_ctrls(r); cdp_disable(); rmdir_all_sub(); static_branch_disable(&rdt_enable_key); diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index f369cb8db0d5..406d7a6532f9 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -29,26 +29,77 @@ #include <asm/intel_rdt.h> /* + * Check whether MBA bandwidth percentage value is correct. The value is + * checked against the minimum and max bandwidth values specified by the + * hardware. The allocated bandwidth percentage is rounded to the next + * control step available on the hardware. + */ +static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) +{ + unsigned long bw; + int ret; + + /* + * Only linear delay values is supported for current Intel SKUs. + */ + if (!r->membw.delay_linear) + return false; + + ret = kstrtoul(buf, 10, &bw); + if (ret) + return false; + + if (bw < r->membw.min_bw || bw > r->default_ctrl) + return false; + + *data = roundup(bw, (unsigned long)r->membw.bw_gran); + return true; +} + +int parse_bw(char *buf, struct rdt_resource *r, struct rdt_domain *d) +{ + unsigned long data; + + if (d->have_new_ctrl) + return -EINVAL; + + if (!bw_validate(buf, &data, r)) + return -EINVAL; + d->new_ctrl = data; + d->have_new_ctrl = true; + + return 0; +} + +/* * Check whether a cache bit mask is valid. The SDM says: * Please note that all (and only) contiguous '1' combinations * are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.). * Additionally Haswell requires at least two bits set. */ -static bool cbm_validate(unsigned long var, struct rdt_resource *r) +static bool cbm_validate(char *buf, unsigned long *data, struct rdt_resource *r) { - unsigned long first_bit, zero_bit; + unsigned long first_bit, zero_bit, val; + unsigned int cbm_len = r->cache.cbm_len; + int ret; + + ret = kstrtoul(buf, 16, &val); + if (ret) + return false; - if (var == 0 || var > r->max_cbm) + if (val == 0 || val > r->default_ctrl) return false; - first_bit = find_first_bit(&var, r->cbm_len); - zero_bit = find_next_zero_bit(&var, r->cbm_len, first_bit); + first_bit = find_first_bit(&val, cbm_len); + zero_bit = find_next_zero_bit(&val, cbm_len, first_bit); - if (find_next_bit(&var, r->cbm_len, zero_bit) < r->cbm_len) + if (find_next_bit(&val, cbm_len, zero_bit) < cbm_len) return false; - if ((zero_bit - first_bit) < r->min_cbm_bits) + if ((zero_bit - first_bit) < r->cache.min_cbm_bits) return false; + + *data = val; return true; } @@ -56,17 +107,17 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r) * Read one cache bit mask (hex). Check that it is valid for the current * resource type. */ -static int parse_cbm(char *buf, struct rdt_resource *r) +int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) { unsigned long data; - int ret; - ret = kstrtoul(buf, 16, &data); - if (ret) - return ret; - if (!cbm_validate(data, r)) + if (d->have_new_ctrl) return -EINVAL; - r->tmp_cbms[r->num_tmp_cbms++] = data; + + if(!cbm_validate(buf, &data, r)) + return -EINVAL; + d->new_ctrl = data; + d->have_new_ctrl = true; return 0; } @@ -74,8 +125,8 @@ static int parse_cbm(char *buf, struct rdt_resource *r) /* * For each domain in this resource we expect to find a series of: * id=mask - * separated by ";". The "id" is in decimal, and must appear in the - * right order. + * separated by ";". The "id" is in decimal, and must match one of + * the "id"s for this resource. */ static int parse_line(char *line, struct rdt_resource *r) { @@ -83,21 +134,22 @@ static int parse_line(char *line, struct rdt_resource *r) struct rdt_domain *d; unsigned long dom_id; +next: + if (!line || line[0] == '\0') + return 0; + dom = strsep(&line, ";"); + id = strsep(&dom, "="); + if (!dom || kstrtoul(id, 10, &dom_id)) + return -EINVAL; + dom = strim(dom); list_for_each_entry(d, &r->domains, list) { - dom = strsep(&line, ";"); - if (!dom) - return -EINVAL; - id = strsep(&dom, "="); - if (kstrtoul(id, 10, &dom_id) || dom_id != d->id) - return -EINVAL; - if (parse_cbm(dom, r)) - return -EINVAL; + if (d->id == dom_id) { + if (r->parse_ctrlval(dom, r, d)) + return -EINVAL; + goto next; + } } - - /* Any garbage at the end of the line? */ - if (line && line[0]) - return -EINVAL; - return 0; + return -EINVAL; } static int update_domains(struct rdt_resource *r, int closid) @@ -105,7 +157,7 @@ static int update_domains(struct rdt_resource *r, int closid) struct msr_param msr_param; cpumask_var_t cpu_mask; struct rdt_domain *d; - int cpu, idx = 0; + int cpu; if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL)) return -ENOMEM; @@ -115,30 +167,46 @@ static int update_domains(struct rdt_resource *r, int closid) msr_param.res = r; list_for_each_entry(d, &r->domains, list) { - cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); - d->cbm[msr_param.low] = r->tmp_cbms[idx++]; + if (d->have_new_ctrl && d->new_ctrl != d->ctrl_val[closid]) { + cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); + d->ctrl_val[closid] = d->new_ctrl; + } } + if (cpumask_empty(cpu_mask)) + goto done; cpu = get_cpu(); /* Update CBM on this cpu if it's in cpu_mask. */ if (cpumask_test_cpu(cpu, cpu_mask)) - rdt_cbm_update(&msr_param); + rdt_ctrl_update(&msr_param); /* Update CBM on other cpus. */ - smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1); + smp_call_function_many(cpu_mask, rdt_ctrl_update, &msr_param, 1); put_cpu(); +done: free_cpumask_var(cpu_mask); return 0; } +static int rdtgroup_parse_resource(char *resname, char *tok, int closid) +{ + struct rdt_resource *r; + + for_each_enabled_rdt_resource(r) { + if (!strcmp(resname, r->name) && closid < r->num_closid) + return parse_line(tok, r); + } + return -EINVAL; +} + ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { struct rdtgroup *rdtgrp; + struct rdt_domain *dom; struct rdt_resource *r; char *tok, *resname; int closid, ret = 0; - u32 *l3_cbms = NULL; /* Valid input requires a trailing newline */ if (nbytes == 0 || buf[nbytes - 1] != '\n') @@ -153,44 +221,20 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, closid = rdtgrp->closid; - /* get scratch space to save all the masks while we validate input */ for_each_enabled_rdt_resource(r) { - r->tmp_cbms = kcalloc(r->num_domains, sizeof(*l3_cbms), - GFP_KERNEL); - if (!r->tmp_cbms) { - ret = -ENOMEM; - goto out; - } - r->num_tmp_cbms = 0; + list_for_each_entry(dom, &r->domains, list) + dom->have_new_ctrl = false; } while ((tok = strsep(&buf, "\n")) != NULL) { - resname = strsep(&tok, ":"); + resname = strim(strsep(&tok, ":")); if (!tok) { ret = -EINVAL; goto out; } - for_each_enabled_rdt_resource(r) { - if (!strcmp(resname, r->name) && - closid < r->num_closid) { - ret = parse_line(tok, r); - if (ret) - goto out; - break; - } - } - if (!r->name) { - ret = -EINVAL; - goto out; - } - } - - /* Did the parser find all the masks we need? */ - for_each_enabled_rdt_resource(r) { - if (r->num_tmp_cbms != r->num_domains) { - ret = -EINVAL; + ret = rdtgroup_parse_resource(resname, tok, closid); + if (ret) goto out; - } } for_each_enabled_rdt_resource(r) { @@ -201,10 +245,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, out: rdtgroup_kn_unlock(of->kn); - for_each_enabled_rdt_resource(r) { - kfree(r->tmp_cbms); - r->tmp_cbms = NULL; - } return ret ?: nbytes; } @@ -213,11 +253,12 @@ static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid) struct rdt_domain *dom; bool sep = false; - seq_printf(s, "%s:", r->name); + seq_printf(s, "%*s:", max_name_width, r->name); list_for_each_entry(dom, &r->domains, list) { if (sep) seq_puts(s, ";"); - seq_printf(s, "%d=%x", dom->id, dom->cbm[closid]); + seq_printf(s, r->format_str, dom->id, max_data_width, + dom->ctrl_val[closid]); sep = true; } seq_puts(s, "\n"); diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile index a3311c886194..43051f0777d4 100644 --- a/arch/x86/kernel/cpu/mcheck/Makefile +++ b/arch/x86/kernel/cpu/mcheck/Makefile @@ -9,3 +9,5 @@ obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o obj-$(CONFIG_ACPI_APEI) += mce-apei.o + +obj-$(CONFIG_X86_MCELOG_LEGACY) += dev-mcelog.o diff --git a/arch/x86/kernel/cpu/mcheck/dev-mcelog.c b/arch/x86/kernel/cpu/mcheck/dev-mcelog.c new file mode 100644 index 000000000000..9c632cb88546 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/dev-mcelog.c @@ -0,0 +1,397 @@ +/* + * /dev/mcelog driver + * + * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. + * Rest from unknown author(s). + * 2004 Andi Kleen. Rewrote most of it. + * Copyright 2008 Intel Corporation + * Author: Andi Kleen + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/miscdevice.h> +#include <linux/slab.h> +#include <linux/kmod.h> +#include <linux/poll.h> + +#include "mce-internal.h" + +static DEFINE_MUTEX(mce_chrdev_read_mutex); + +static char mce_helper[128]; +static char *mce_helper_argv[2] = { mce_helper, NULL }; + +#define mce_log_get_idx_check(p) \ +({ \ + RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held() && \ + !lockdep_is_held(&mce_chrdev_read_mutex), \ + "suspicious mce_log_get_idx_check() usage"); \ + smp_load_acquire(&(p)); \ +}) + +/* + * Lockless MCE logging infrastructure. + * This avoids deadlocks on printk locks without having to break locks. Also + * separate MCEs from kernel messages to avoid bogus bug reports. + */ + +static struct mce_log_buffer mcelog = { + .signature = MCE_LOG_SIGNATURE, + .len = MCE_LOG_LEN, + .recordlen = sizeof(struct mce), +}; + +static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait); + +/* User mode helper program triggered by machine check event */ +extern char mce_helper[128]; + +static int dev_mce_log(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct mce *mce = (struct mce *)data; + unsigned int next, entry; + + wmb(); + for (;;) { + entry = mce_log_get_idx_check(mcelog.next); + for (;;) { + + /* + * When the buffer fills up discard new entries. + * Assume that the earlier errors are the more + * interesting ones: + */ + if (entry >= MCE_LOG_LEN) { + set_bit(MCE_OVERFLOW, + (unsigned long *)&mcelog.flags); + return NOTIFY_OK; + } + /* Old left over entry. Skip: */ + if (mcelog.entry[entry].finished) { + entry++; + continue; + } + break; + } + smp_rmb(); + next = entry + 1; + if (cmpxchg(&mcelog.next, entry, next) == entry) + break; + } + memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); + wmb(); + mcelog.entry[entry].finished = 1; + wmb(); + + /* wake processes polling /dev/mcelog */ + wake_up_interruptible(&mce_chrdev_wait); + + return NOTIFY_OK; +} + +static struct notifier_block dev_mcelog_nb = { + .notifier_call = dev_mce_log, + .priority = MCE_PRIO_MCELOG, +}; + +static void mce_do_trigger(struct work_struct *work) +{ + call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT); +} + +static DECLARE_WORK(mce_trigger_work, mce_do_trigger); + + +void mce_work_trigger(void) +{ + if (mce_helper[0]) + schedule_work(&mce_trigger_work); +} + +static ssize_t +show_trigger(struct device *s, struct device_attribute *attr, char *buf) +{ + strcpy(buf, mce_helper); + strcat(buf, "\n"); + return strlen(mce_helper) + 1; +} + +static ssize_t set_trigger(struct device *s, struct device_attribute *attr, + const char *buf, size_t siz) +{ + char *p; + + strncpy(mce_helper, buf, sizeof(mce_helper)); + mce_helper[sizeof(mce_helper)-1] = 0; + p = strchr(mce_helper, '\n'); + + if (p) + *p = 0; + + return strlen(mce_helper) + !!p; +} + +DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger); + +/* + * mce_chrdev: Character device /dev/mcelog to read and clear the MCE log. + */ + +static DEFINE_SPINLOCK(mce_chrdev_state_lock); +static int mce_chrdev_open_count; /* #times opened */ +static int mce_chrdev_open_exclu; /* already open exclusive? */ + +static int mce_chrdev_open(struct inode *inode, struct file *file) +{ + spin_lock(&mce_chrdev_state_lock); + + if (mce_chrdev_open_exclu || + (mce_chrdev_open_count && (file->f_flags & O_EXCL))) { + spin_unlock(&mce_chrdev_state_lock); + + return -EBUSY; + } + + if (file->f_flags & O_EXCL) + mce_chrdev_open_exclu = 1; + mce_chrdev_open_count++; + + spin_unlock(&mce_chrdev_state_lock); + + return nonseekable_open(inode, file); +} + +static int mce_chrdev_release(struct inode *inode, struct file *file) +{ + spin_lock(&mce_chrdev_state_lock); + + mce_chrdev_open_count--; + mce_chrdev_open_exclu = 0; + + spin_unlock(&mce_chrdev_state_lock); + + return 0; +} + +static void collect_tscs(void *data) +{ + unsigned long *cpu_tsc = (unsigned long *)data; + + cpu_tsc[smp_processor_id()] = rdtsc(); +} + +static int mce_apei_read_done; + +/* Collect MCE record of previous boot in persistent storage via APEI ERST. */ +static int __mce_read_apei(char __user **ubuf, size_t usize) +{ + int rc; + u64 record_id; + struct mce m; + + if (usize < sizeof(struct mce)) + return -EINVAL; + + rc = apei_read_mce(&m, &record_id); + /* Error or no more MCE record */ + if (rc <= 0) { + mce_apei_read_done = 1; + /* + * When ERST is disabled, mce_chrdev_read() should return + * "no record" instead of "no device." + */ + if (rc == -ENODEV) + return 0; + return rc; + } + rc = -EFAULT; + if (copy_to_user(*ubuf, &m, sizeof(struct mce))) + return rc; + /* + * In fact, we should have cleared the record after that has + * been flushed to the disk or sent to network in + * /sbin/mcelog, but we have no interface to support that now, + * so just clear it to avoid duplication. + */ + rc = apei_clear_mce(record_id); + if (rc) { + mce_apei_read_done = 1; + return rc; + } + *ubuf += sizeof(struct mce); + + return 0; +} + +static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf, + size_t usize, loff_t *off) +{ + char __user *buf = ubuf; + unsigned long *cpu_tsc; + unsigned prev, next; + int i, err; + + cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL); + if (!cpu_tsc) + return -ENOMEM; + + mutex_lock(&mce_chrdev_read_mutex); + + if (!mce_apei_read_done) { + err = __mce_read_apei(&buf, usize); + if (err || buf != ubuf) + goto out; + } + + next = mce_log_get_idx_check(mcelog.next); + + /* Only supports full reads right now */ + err = -EINVAL; + if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) + goto out; + + err = 0; + prev = 0; + do { + for (i = prev; i < next; i++) { + unsigned long start = jiffies; + struct mce *m = &mcelog.entry[i]; + + while (!m->finished) { + if (time_after_eq(jiffies, start + 2)) { + memset(m, 0, sizeof(*m)); + goto timeout; + } + cpu_relax(); + } + smp_rmb(); + err |= copy_to_user(buf, m, sizeof(*m)); + buf += sizeof(*m); +timeout: + ; + } + + memset(mcelog.entry + prev, 0, + (next - prev) * sizeof(struct mce)); + prev = next; + next = cmpxchg(&mcelog.next, prev, 0); + } while (next != prev); + + synchronize_sched(); + + /* + * Collect entries that were still getting written before the + * synchronize. + */ + on_each_cpu(collect_tscs, cpu_tsc, 1); + + for (i = next; i < MCE_LOG_LEN; i++) { + struct mce *m = &mcelog.entry[i]; + + if (m->finished && m->tsc < cpu_tsc[m->cpu]) { + err |= copy_to_user(buf, m, sizeof(*m)); + smp_rmb(); + buf += sizeof(*m); + memset(m, 0, sizeof(*m)); + } + } + + if (err) + err = -EFAULT; + +out: + mutex_unlock(&mce_chrdev_read_mutex); + kfree(cpu_tsc); + + return err ? err : buf - ubuf; +} + +static unsigned int mce_chrdev_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &mce_chrdev_wait, wait); + if (READ_ONCE(mcelog.next)) + return POLLIN | POLLRDNORM; + if (!mce_apei_read_done && apei_check_mce()) + return POLLIN | POLLRDNORM; + return 0; +} + +static long mce_chrdev_ioctl(struct file *f, unsigned int cmd, + unsigned long arg) +{ + int __user *p = (int __user *)arg; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + switch (cmd) { + case MCE_GET_RECORD_LEN: + return put_user(sizeof(struct mce), p); + case MCE_GET_LOG_LEN: + return put_user(MCE_LOG_LEN, p); + case MCE_GETCLEAR_FLAGS: { + unsigned flags; + + do { + flags = mcelog.flags; + } while (cmpxchg(&mcelog.flags, flags, 0) != flags); + + return put_user(flags, p); + } + default: + return -ENOTTY; + } +} + +static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf, + size_t usize, loff_t *off); + +void register_mce_write_callback(ssize_t (*fn)(struct file *filp, + const char __user *ubuf, + size_t usize, loff_t *off)) +{ + mce_write = fn; +} +EXPORT_SYMBOL_GPL(register_mce_write_callback); + +static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, + size_t usize, loff_t *off) +{ + if (mce_write) + return mce_write(filp, ubuf, usize, off); + else + return -EINVAL; +} + +static const struct file_operations mce_chrdev_ops = { + .open = mce_chrdev_open, + .release = mce_chrdev_release, + .read = mce_chrdev_read, + .write = mce_chrdev_write, + .poll = mce_chrdev_poll, + .unlocked_ioctl = mce_chrdev_ioctl, + .llseek = no_llseek, +}; + +static struct miscdevice mce_chrdev_device = { + MISC_MCELOG_MINOR, + "mcelog", + &mce_chrdev_ops, +}; + +static __init int dev_mcelog_init_device(void) +{ + int err; + + /* register character device /dev/mcelog */ + err = misc_register(&mce_chrdev_device); + if (err) { + pr_err("Unable to init device /dev/mcelog (rc: %d)\n", err); + return err; + } + mce_register_decode_chain(&dev_mcelog_nb); + return 0; +} +device_initcall_sync(dev_mcelog_init_device); diff --git a/arch/x86/kernel/cpu/mcheck/mce-genpool.c b/arch/x86/kernel/cpu/mcheck/mce-genpool.c index 1e5a50c11d3c..217cd4449bc9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-genpool.c +++ b/arch/x86/kernel/cpu/mcheck/mce-genpool.c @@ -85,7 +85,7 @@ void mce_gen_pool_process(struct work_struct *__unused) head = llist_reverse_order(head); llist_for_each_entry_safe(node, tmp, head, llnode) { mce = &node->mce; - atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); + blocking_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node)); } } diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h index 903043e6a62b..654ad0668d72 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-internal.h +++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h @@ -13,7 +13,7 @@ enum severity_level { MCE_PANIC_SEVERITY, }; -extern struct atomic_notifier_head x86_mce_decoder_chain; +extern struct blocking_notifier_head x86_mce_decoder_chain; #define ATTR_LEN 16 #define INITIAL_CHECK_INTERVAL 5 * 60 /* 5 minutes */ @@ -96,3 +96,11 @@ static inline bool mce_cmp(struct mce *m1, struct mce *m2) m1->addr != m2->addr || m1->misc != m2->misc; } + +extern struct device_attribute dev_attr_trigger; + +#ifdef CONFIG_X86_MCELOG_LEGACY +extern void mce_work_trigger(void); +#else +static inline void mce_work_trigger(void) { } +#endif diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 8e9725c607ea..5abd4bf73d6e 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -35,6 +35,7 @@ #include <linux/poll.h> #include <linux/nmi.h> #include <linux/cpu.h> +#include <linux/ras.h> #include <linux/smp.h> #include <linux/fs.h> #include <linux/mm.h> @@ -49,18 +50,11 @@ #include <asm/tlbflush.h> #include <asm/mce.h> #include <asm/msr.h> +#include <asm/reboot.h> #include "mce-internal.h" -static DEFINE_MUTEX(mce_chrdev_read_mutex); - -#define mce_log_get_idx_check(p) \ -({ \ - RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held() && \ - !lockdep_is_held(&mce_chrdev_read_mutex), \ - "suspicious mce_log_get_idx_check() usage"); \ - smp_load_acquire(&(p)); \ -}) +static DEFINE_MUTEX(mce_log_mutex); #define CREATE_TRACE_POINTS #include <trace/events/mce.h> @@ -85,15 +79,9 @@ struct mca_config mca_cfg __read_mostly = { .monarch_timeout = -1 }; -/* User mode helper program triggered by machine check event */ -static unsigned long mce_need_notify; -static char mce_helper[128]; -static char *mce_helper_argv[2] = { mce_helper, NULL }; - -static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait); - static DEFINE_PER_CPU(struct mce, mces_seen); -static int cpu_missing; +static unsigned long mce_need_notify; +static int cpu_missing; /* * MCA banks polled by the period polling timer for corrected events. @@ -121,7 +109,7 @@ static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. */ -ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); +BLOCKING_NOTIFIER_HEAD(x86_mce_decoder_chain); /* Do initial initialization of a struct mce */ void mce_setup(struct mce *m) @@ -143,82 +131,38 @@ void mce_setup(struct mce *m) DEFINE_PER_CPU(struct mce, injectm); EXPORT_PER_CPU_SYMBOL_GPL(injectm); -/* - * Lockless MCE logging infrastructure. - * This avoids deadlocks on printk locks without having to break locks. Also - * separate MCEs from kernel messages to avoid bogus bug reports. - */ - -static struct mce_log mcelog = { - .signature = MCE_LOG_SIGNATURE, - .len = MCE_LOG_LEN, - .recordlen = sizeof(struct mce), -}; - -void mce_log(struct mce *mce) +void mce_log(struct mce *m) { - unsigned next, entry; - - /* Emit the trace record: */ - trace_mce_record(mce); - - if (!mce_gen_pool_add(mce)) + if (!mce_gen_pool_add(m)) irq_work_queue(&mce_irq_work); - - wmb(); - for (;;) { - entry = mce_log_get_idx_check(mcelog.next); - for (;;) { - - /* - * When the buffer fills up discard new entries. - * Assume that the earlier errors are the more - * interesting ones: - */ - if (entry >= MCE_LOG_LEN) { - set_bit(MCE_OVERFLOW, - (unsigned long *)&mcelog.flags); - return; - } - /* Old left over entry. Skip: */ - if (mcelog.entry[entry].finished) { - entry++; - continue; - } - break; - } - smp_rmb(); - next = entry + 1; - if (cmpxchg(&mcelog.next, entry, next) == entry) - break; - } - memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); - wmb(); - mcelog.entry[entry].finished = 1; - wmb(); - - set_bit(0, &mce_need_notify); } void mce_inject_log(struct mce *m) { - mutex_lock(&mce_chrdev_read_mutex); + mutex_lock(&mce_log_mutex); mce_log(m); - mutex_unlock(&mce_chrdev_read_mutex); + mutex_unlock(&mce_log_mutex); } EXPORT_SYMBOL_GPL(mce_inject_log); static struct notifier_block mce_srao_nb; +/* + * We run the default notifier if we have only the SRAO, the first and the + * default notifier registered. I.e., the mandatory NUM_DEFAULT_NOTIFIERS + * notifiers registered on the chain. + */ +#define NUM_DEFAULT_NOTIFIERS 3 static atomic_t num_notifiers; void mce_register_decode_chain(struct notifier_block *nb) { - atomic_inc(&num_notifiers); + if (WARN_ON(nb->priority > MCE_PRIO_MCELOG && nb->priority < MCE_PRIO_EDAC)) + return; - WARN_ON(nb->priority > MCE_PRIO_LOWEST && nb->priority < MCE_PRIO_EDAC); + atomic_inc(&num_notifiers); - atomic_notifier_chain_register(&x86_mce_decoder_chain, nb); + blocking_notifier_chain_register(&x86_mce_decoder_chain, nb); } EXPORT_SYMBOL_GPL(mce_register_decode_chain); @@ -226,7 +170,7 @@ void mce_unregister_decode_chain(struct notifier_block *nb) { atomic_dec(&num_notifiers); - atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb); + blocking_notifier_chain_unregister(&x86_mce_decoder_chain, nb); } EXPORT_SYMBOL_GPL(mce_unregister_decode_chain); @@ -319,18 +263,7 @@ static void __print_mce(struct mce *m) static void print_mce(struct mce *m) { - int ret = 0; - __print_mce(m); - - /* - * Print out human-readable details about the MCE error, - * (if the CPU has an implementation for that) - */ - ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); - if (ret == NOTIFY_STOP) - return; - pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n"); } @@ -519,7 +452,6 @@ static void mce_schedule_work(void) static void mce_irq_work_cb(struct irq_work *entry) { - mce_notify_irq(); mce_schedule_work(); } @@ -548,20 +480,97 @@ static void mce_report_event(struct pt_regs *regs) */ static int mce_usable_address(struct mce *m) { - if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV)) + if (!(m->status & MCI_STATUS_ADDRV)) return 0; /* Checks after this one are Intel-specific: */ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) return 1; + if (!(m->status & MCI_STATUS_MISCV)) + return 0; + if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT) return 0; + if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS) return 0; + return 1; } +static bool memory_error(struct mce *m) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + if (c->x86_vendor == X86_VENDOR_AMD) { + /* ErrCodeExt[20:16] */ + u8 xec = (m->status >> 16) & 0x1f; + + return (xec == 0x0 || xec == 0x8); + } else if (c->x86_vendor == X86_VENDOR_INTEL) { + /* + * Intel SDM Volume 3B - 15.9.2 Compound Error Codes + * + * Bit 7 of the MCACOD field of IA32_MCi_STATUS is used for + * indicating a memory error. Bit 8 is used for indicating a + * cache hierarchy error. The combination of bit 2 and bit 3 + * is used for indicating a `generic' cache hierarchy error + * But we can't just blindly check the above bits, because if + * bit 11 is set, then it is a bus/interconnect error - and + * either way the above bits just gives more detail on what + * bus/interconnect error happened. Note that bit 12 can be + * ignored, as it's the "filter" bit. + */ + return (m->status & 0xef80) == BIT(7) || + (m->status & 0xef00) == BIT(8) || + (m->status & 0xeffc) == 0xc; + } + + return false; +} + +static bool cec_add_mce(struct mce *m) +{ + if (!m) + return false; + + /* We eat only correctable DRAM errors with usable addresses. */ + if (memory_error(m) && + !(m->status & MCI_STATUS_UC) && + mce_usable_address(m)) + if (!cec_add_elem(m->addr >> PAGE_SHIFT)) + return true; + + return false; +} + +static int mce_first_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct mce *m = (struct mce *)data; + + if (!m) + return NOTIFY_DONE; + + if (cec_add_mce(m)) + return NOTIFY_STOP; + + /* Emit the trace record: */ + trace_mce_record(m); + + set_bit(0, &mce_need_notify); + + mce_notify_irq(); + + return NOTIFY_DONE; +} + +static struct notifier_block first_nb = { + .notifier_call = mce_first_notifier, + .priority = MCE_PRIO_FIRST, +}; + static int srao_decode_notifier(struct notifier_block *nb, unsigned long val, void *data) { @@ -591,11 +600,7 @@ static int mce_default_notifier(struct notifier_block *nb, unsigned long val, if (!m) return NOTIFY_DONE; - /* - * Run the default notifier if we have only the SRAO - * notifier and us registered. - */ - if (atomic_read(&num_notifiers) > 2) + if (atomic_read(&num_notifiers) > NUM_DEFAULT_NOTIFIERS) return NOTIFY_DONE; __print_mce(m); @@ -648,37 +653,6 @@ static void mce_read_aux(struct mce *m, int i) } } -static bool memory_error(struct mce *m) -{ - struct cpuinfo_x86 *c = &boot_cpu_data; - - if (c->x86_vendor == X86_VENDOR_AMD) { - /* ErrCodeExt[20:16] */ - u8 xec = (m->status >> 16) & 0x1f; - - return (xec == 0x0 || xec == 0x8); - } else if (c->x86_vendor == X86_VENDOR_INTEL) { - /* - * Intel SDM Volume 3B - 15.9.2 Compound Error Codes - * - * Bit 7 of the MCACOD field of IA32_MCi_STATUS is used for - * indicating a memory error. Bit 8 is used for indicating a - * cache hierarchy error. The combination of bit 2 and bit 3 - * is used for indicating a `generic' cache hierarchy error - * But we can't just blindly check the above bits, because if - * bit 11 is set, then it is a bus/interconnect error - and - * either way the above bits just gives more detail on what - * bus/interconnect error happened. Note that bit 12 can be - * ignored, as it's the "filter" bit. - */ - return (m->status & 0xef80) == BIT(7) || - (m->status & 0xef00) == BIT(8) || - (m->status & 0xeffc) == 0xc; - } - - return false; -} - DEFINE_PER_CPU(unsigned, mce_poll_count); /* @@ -1127,9 +1101,22 @@ void do_machine_check(struct pt_regs *regs, long error_code) * on Intel. */ int lmce = 1; + int cpu = smp_processor_id(); - /* If this CPU is offline, just bail out. */ - if (cpu_is_offline(smp_processor_id())) { + /* + * Cases where we avoid rendezvous handler timeout: + * 1) If this CPU is offline. + * + * 2) If crashing_cpu was set, e.g. we're entering kdump and we need to + * skip those CPUs which remain looping in the 1st kernel - see + * crash_nmi_callback(). + * + * Note: there still is a small window between kexec-ing and the new, + * kdump kernel establishing a new #MC handler where a broadcasted MCE + * might not get handled properly. + */ + if (cpu_is_offline(cpu) || + (crashing_cpu != -1 && crashing_cpu != cpu)) { u64 mcgstatus; mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS); @@ -1399,13 +1386,6 @@ static void mce_timer_delete_all(void) del_timer_sync(&per_cpu(mce_timer, cpu)); } -static void mce_do_trigger(struct work_struct *work) -{ - call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT); -} - -static DECLARE_WORK(mce_trigger_work, mce_do_trigger); - /* * Notify the user(s) about new machine check events. * Can be called from interrupt context, but not from machine check/NMI @@ -1417,11 +1397,7 @@ int mce_notify_irq(void) static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2); if (test_and_clear_bit(0, &mce_need_notify)) { - /* wake processes polling /dev/mcelog */ - wake_up_interruptible(&mce_chrdev_wait); - - if (mce_helper[0]) - schedule_work(&mce_trigger_work); + mce_work_trigger(); if (__ratelimit(&ratelimit)) pr_info(HW_ERR "Machine check events logged\n"); @@ -1688,30 +1664,35 @@ static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c) return 0; } -static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) +/* + * Init basic CPU features needed for early decoding of MCEs. + */ +static void __mcheck_cpu_init_early(struct cpuinfo_x86 *c) { - switch (c->x86_vendor) { - case X86_VENDOR_INTEL: - mce_intel_feature_init(c); - mce_adjust_timer = cmci_intel_adjust_timer; - break; - - case X86_VENDOR_AMD: { + if (c->x86_vendor == X86_VENDOR_AMD) { mce_flags.overflow_recov = !!cpu_has(c, X86_FEATURE_OVERFLOW_RECOV); mce_flags.succor = !!cpu_has(c, X86_FEATURE_SUCCOR); mce_flags.smca = !!cpu_has(c, X86_FEATURE_SMCA); - /* - * Install proper ops for Scalable MCA enabled processors - */ if (mce_flags.smca) { msr_ops.ctl = smca_ctl_reg; msr_ops.status = smca_status_reg; msr_ops.addr = smca_addr_reg; msr_ops.misc = smca_misc_reg; } - mce_amd_feature_init(c); + } +} + +static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) +{ + switch (c->x86_vendor) { + case X86_VENDOR_INTEL: + mce_intel_feature_init(c); + mce_adjust_timer = cmci_intel_adjust_timer; + break; + case X86_VENDOR_AMD: { + mce_amd_feature_init(c); break; } @@ -1798,6 +1779,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c) machine_check_vector = do_machine_check; + __mcheck_cpu_init_early(c); __mcheck_cpu_init_generic(); __mcheck_cpu_init_vendor(c); __mcheck_cpu_init_clear_banks(); @@ -1823,252 +1805,6 @@ void mcheck_cpu_clear(struct cpuinfo_x86 *c) } -/* - * mce_chrdev: Character device /dev/mcelog to read and clear the MCE log. - */ - -static DEFINE_SPINLOCK(mce_chrdev_state_lock); -static int mce_chrdev_open_count; /* #times opened */ -static int mce_chrdev_open_exclu; /* already open exclusive? */ - -static int mce_chrdev_open(struct inode *inode, struct file *file) -{ - spin_lock(&mce_chrdev_state_lock); - - if (mce_chrdev_open_exclu || - (mce_chrdev_open_count && (file->f_flags & O_EXCL))) { - spin_unlock(&mce_chrdev_state_lock); - - return -EBUSY; - } - - if (file->f_flags & O_EXCL) - mce_chrdev_open_exclu = 1; - mce_chrdev_open_count++; - - spin_unlock(&mce_chrdev_state_lock); - - return nonseekable_open(inode, file); -} - -static int mce_chrdev_release(struct inode *inode, struct file *file) -{ - spin_lock(&mce_chrdev_state_lock); - - mce_chrdev_open_count--; - mce_chrdev_open_exclu = 0; - - spin_unlock(&mce_chrdev_state_lock); - - return 0; -} - -static void collect_tscs(void *data) -{ - unsigned long *cpu_tsc = (unsigned long *)data; - - cpu_tsc[smp_processor_id()] = rdtsc(); -} - -static int mce_apei_read_done; - -/* Collect MCE record of previous boot in persistent storage via APEI ERST. */ -static int __mce_read_apei(char __user **ubuf, size_t usize) -{ - int rc; - u64 record_id; - struct mce m; - - if (usize < sizeof(struct mce)) - return -EINVAL; - - rc = apei_read_mce(&m, &record_id); - /* Error or no more MCE record */ - if (rc <= 0) { - mce_apei_read_done = 1; - /* - * When ERST is disabled, mce_chrdev_read() should return - * "no record" instead of "no device." - */ - if (rc == -ENODEV) - return 0; - return rc; - } - rc = -EFAULT; - if (copy_to_user(*ubuf, &m, sizeof(struct mce))) - return rc; - /* - * In fact, we should have cleared the record after that has - * been flushed to the disk or sent to network in - * /sbin/mcelog, but we have no interface to support that now, - * so just clear it to avoid duplication. - */ - rc = apei_clear_mce(record_id); - if (rc) { - mce_apei_read_done = 1; - return rc; - } - *ubuf += sizeof(struct mce); - - return 0; -} - -static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf, - size_t usize, loff_t *off) -{ - char __user *buf = ubuf; - unsigned long *cpu_tsc; - unsigned prev, next; - int i, err; - - cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL); - if (!cpu_tsc) - return -ENOMEM; - - mutex_lock(&mce_chrdev_read_mutex); - - if (!mce_apei_read_done) { - err = __mce_read_apei(&buf, usize); - if (err || buf != ubuf) - goto out; - } - - next = mce_log_get_idx_check(mcelog.next); - - /* Only supports full reads right now */ - err = -EINVAL; - if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) - goto out; - - err = 0; - prev = 0; - do { - for (i = prev; i < next; i++) { - unsigned long start = jiffies; - struct mce *m = &mcelog.entry[i]; - - while (!m->finished) { - if (time_after_eq(jiffies, start + 2)) { - memset(m, 0, sizeof(*m)); - goto timeout; - } - cpu_relax(); - } - smp_rmb(); - err |= copy_to_user(buf, m, sizeof(*m)); - buf += sizeof(*m); -timeout: - ; - } - - memset(mcelog.entry + prev, 0, - (next - prev) * sizeof(struct mce)); - prev = next; - next = cmpxchg(&mcelog.next, prev, 0); - } while (next != prev); - - synchronize_sched(); - - /* - * Collect entries that were still getting written before the - * synchronize. - */ - on_each_cpu(collect_tscs, cpu_tsc, 1); - - for (i = next; i < MCE_LOG_LEN; i++) { - struct mce *m = &mcelog.entry[i]; - - if (m->finished && m->tsc < cpu_tsc[m->cpu]) { - err |= copy_to_user(buf, m, sizeof(*m)); - smp_rmb(); - buf += sizeof(*m); - memset(m, 0, sizeof(*m)); - } - } - - if (err) - err = -EFAULT; - -out: - mutex_unlock(&mce_chrdev_read_mutex); - kfree(cpu_tsc); - - return err ? err : buf - ubuf; -} - -static unsigned int mce_chrdev_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &mce_chrdev_wait, wait); - if (READ_ONCE(mcelog.next)) - return POLLIN | POLLRDNORM; - if (!mce_apei_read_done && apei_check_mce()) - return POLLIN | POLLRDNORM; - return 0; -} - -static long mce_chrdev_ioctl(struct file *f, unsigned int cmd, - unsigned long arg) -{ - int __user *p = (int __user *)arg; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - switch (cmd) { - case MCE_GET_RECORD_LEN: - return put_user(sizeof(struct mce), p); - case MCE_GET_LOG_LEN: - return put_user(MCE_LOG_LEN, p); - case MCE_GETCLEAR_FLAGS: { - unsigned flags; - - do { - flags = mcelog.flags; - } while (cmpxchg(&mcelog.flags, flags, 0) != flags); - - return put_user(flags, p); - } - default: - return -ENOTTY; - } -} - -static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf, - size_t usize, loff_t *off); - -void register_mce_write_callback(ssize_t (*fn)(struct file *filp, - const char __user *ubuf, - size_t usize, loff_t *off)) -{ - mce_write = fn; -} -EXPORT_SYMBOL_GPL(register_mce_write_callback); - -static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, - size_t usize, loff_t *off) -{ - if (mce_write) - return mce_write(filp, ubuf, usize, off); - else - return -EINVAL; -} - -static const struct file_operations mce_chrdev_ops = { - .open = mce_chrdev_open, - .release = mce_chrdev_release, - .read = mce_chrdev_read, - .write = mce_chrdev_write, - .poll = mce_chrdev_poll, - .unlocked_ioctl = mce_chrdev_ioctl, - .llseek = no_llseek, -}; - -static struct miscdevice mce_chrdev_device = { - MISC_MCELOG_MINOR, - "mcelog", - &mce_chrdev_ops, -}; - static void __mce_disable_bank(void *arg) { int bank = *((int *)arg); @@ -2142,6 +1878,7 @@ __setup("mce", mcheck_enable); int __init mcheck_init(void) { mcheck_intel_therm_init(); + mce_register_decode_chain(&first_nb); mce_register_decode_chain(&mce_srao_nb); mce_register_decode_chain(&mce_default_nb); mcheck_vendor_init_severity(); @@ -2286,29 +2023,6 @@ static ssize_t set_bank(struct device *s, struct device_attribute *attr, return size; } -static ssize_t -show_trigger(struct device *s, struct device_attribute *attr, char *buf) -{ - strcpy(buf, mce_helper); - strcat(buf, "\n"); - return strlen(mce_helper) + 1; -} - -static ssize_t set_trigger(struct device *s, struct device_attribute *attr, - const char *buf, size_t siz) -{ - char *p; - - strncpy(mce_helper, buf, sizeof(mce_helper)); - mce_helper[sizeof(mce_helper)-1] = 0; - p = strchr(mce_helper, '\n'); - - if (p) - *p = 0; - - return strlen(mce_helper) + !!p; -} - static ssize_t set_ignore_ce(struct device *s, struct device_attribute *attr, const char *buf, size_t size) @@ -2365,7 +2079,6 @@ static ssize_t store_int_with_restart(struct device *s, return ret; } -static DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger); static DEVICE_INT_ATTR(tolerant, 0644, mca_cfg.tolerant); static DEVICE_INT_ATTR(monarch_timeout, 0644, mca_cfg.monarch_timeout); static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce); @@ -2388,7 +2101,9 @@ static struct dev_ext_attribute dev_attr_cmci_disabled = { static struct device_attribute *mce_device_attrs[] = { &dev_attr_tolerant.attr, &dev_attr_check_interval.attr, +#ifdef CONFIG_X86_MCELOG_LEGACY &dev_attr_trigger, +#endif &dev_attr_monarch_timeout.attr, &dev_attr_dont_log_ce.attr, &dev_attr_ignore_ce.attr, @@ -2562,7 +2277,6 @@ static __init void mce_init_banks(void) static __init int mcheck_init_device(void) { - enum cpuhp_state hp_online; int err; if (!mce_available(&boot_cpu_data)) { @@ -2590,21 +2304,11 @@ static __init int mcheck_init_device(void) mce_cpu_online, mce_cpu_pre_down); if (err < 0) goto err_out_online; - hp_online = err; register_syscore_ops(&mce_syscore_ops); - /* register character device /dev/mcelog */ - err = misc_register(&mce_chrdev_device); - if (err) - goto err_register; - return 0; -err_register: - unregister_syscore_ops(&mce_syscore_ops); - cpuhp_remove_state(hp_online); - err_out_online: cpuhp_remove_state(CPUHP_X86_MCE_DEAD); @@ -2612,7 +2316,7 @@ err_out_mem: free_cpumask_var(mce_device_initialized); err_out: - pr_err("Unable to init device /dev/mcelog (rc: %d)\n", err); + pr_err("Unable to init MCE device (rc: %d)\n", err); return err; } @@ -2691,6 +2395,7 @@ static int __init mcheck_late_init(void) static_branch_inc(&mcsafe_key); mcheck_debugfs_init(); + cec_init(); /* * Flush out everything that has been logged during early boot, now that diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 524cc5780a77..6e4a047e4b68 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -60,7 +60,7 @@ static const char * const th_names[] = { "load_store", "insn_fetch", "combined_unit", - "", + "decode_unit", "northbridge", "execution_unit", }; diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 190b3e6cef4d..e84db79ef272 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -481,6 +481,9 @@ static void intel_ppin_init(struct cpuinfo_x86 *c) case INTEL_FAM6_BROADWELL_XEON_D: case INTEL_FAM6_BROADWELL_X: case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_XEON_PHI_KNL: + case INTEL_FAM6_XEON_PHI_KNM: + if (rdmsrl_safe(MSR_PPIN_CTL, &val)) return; diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 3b442b64c72d..765afd599039 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c @@ -27,7 +27,7 @@ #include <linux/range.h> #include <asm/processor.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mtrr.h> #include <asm/msr.h> @@ -860,7 +860,7 @@ real_trim_memory(unsigned long start_pfn, unsigned long limit_pfn) trim_size <<= PAGE_SHIFT; trim_size -= trim_start; - return e820_update_range(trim_start, trim_size, E820_RAM, E820_RESERVED); + return e820__range_update(trim_start, trim_size, E820_TYPE_RAM, E820_TYPE_RESERVED); } /** @@ -978,7 +978,7 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) WARN_ON(1); pr_info("update e820 for mtrr\n"); - update_e820(); + e820__update_table_print(); return 1; } diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 24e87e74990d..2bce84d91c2b 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -48,7 +48,7 @@ #include <linux/syscore_ops.h> #include <asm/cpufeature.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mtrr.h> #include <asm/msr.h> #include <asm/pat.h> diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 18ca99f2798b..6df621ae62a7 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -31,14 +31,13 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid level\t: %d\n" - "wp\t\t: %s\n", + "wp\t\t: yes\n", static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", - c->cpuid_level, - c->wp_works_ok ? "yes" : "no"); + c->cpuid_level); } #else static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index d9794060fe22..23c23508c012 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -27,6 +27,7 @@ static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_CAT_L3, CPUID_EBX, 1, 0x00000010, 0 }, { X86_FEATURE_CAT_L2, CPUID_EBX, 2, 0x00000010, 0 }, { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 }, + { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 }, { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 8457b4978668..d77d07ab310b 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -16,8 +16,6 @@ static void early_init_transmeta(struct cpuinfo_x86 *c) if (xlvl >= 0x80860001) c->x86_capability[CPUID_8086_0001_EDX] = cpuid_edx(0x80860001); } - - clear_sched_clock_stable(); } static void init_transmeta(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 891f4dad7b2c..22403a28caf5 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -30,7 +30,6 @@ #include <asm/hypervisor.h> #include <asm/timer.h> #include <asm/apic.h> -#include <asm/timer.h> #undef pr_fmt #define pr_fmt(fmt) "vmware: " fmt diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 3741461c63a0..22217ece26c8 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -29,6 +29,7 @@ #include <asm/nmi.h> #include <asm/hw_irq.h> #include <asm/apic.h> +#include <asm/e820/types.h> #include <asm/io_apic.h> #include <asm/hpet.h> #include <linux/kdebug.h> @@ -503,16 +504,16 @@ static int prepare_elf_headers(struct kimage *image, void **addr, return ret; } -static int add_e820_entry(struct boot_params *params, struct e820entry *entry) +static int add_e820_entry(struct boot_params *params, struct e820_entry *entry) { unsigned int nr_e820_entries; nr_e820_entries = params->e820_entries; - if (nr_e820_entries >= E820MAX) + if (nr_e820_entries >= E820_MAX_ENTRIES_ZEROPAGE) return 1; - memcpy(¶ms->e820_map[nr_e820_entries], entry, - sizeof(struct e820entry)); + memcpy(¶ms->e820_table[nr_e820_entries], entry, + sizeof(struct e820_entry)); params->e820_entries++; return 0; } @@ -521,7 +522,7 @@ static int memmap_entry_callback(u64 start, u64 end, void *arg) { struct crash_memmap_data *cmd = arg; struct boot_params *params = cmd->params; - struct e820entry ei; + struct e820_entry ei; ei.addr = start; ei.size = end - start + 1; @@ -560,7 +561,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) { int i, ret = 0; unsigned long flags; - struct e820entry ei; + struct e820_entry ei; struct crash_memmap_data cmd; struct crash_mem *cmem; @@ -574,17 +575,17 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) /* Add first 640K segment */ ei.addr = image->arch.backup_src_start; ei.size = image->arch.backup_src_sz; - ei.type = E820_RAM; + ei.type = E820_TYPE_RAM; add_e820_entry(params, &ei); /* Add ACPI tables */ - cmd.type = E820_ACPI; + cmd.type = E820_TYPE_ACPI; flags = IORESOURCE_MEM | IORESOURCE_BUSY; walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd, memmap_entry_callback); /* Add ACPI Non-volatile Storage */ - cmd.type = E820_NVS; + cmd.type = E820_TYPE_NVS; walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd, memmap_entry_callback); @@ -592,7 +593,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) if (crashk_low_res.end) { ei.addr = crashk_low_res.start; ei.size = crashk_low_res.end - crashk_low_res.start + 1; - ei.type = E820_RAM; + ei.type = E820_TYPE_RAM; add_e820_entry(params, &ei); } @@ -609,7 +610,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) if (ei.size < PAGE_SIZE) continue; ei.addr = cmem->ranges[i].start; - ei.type = E820_RAM; + ei.type = E820_TYPE_RAM; add_e820_entry(params, &ei); } diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 09d4ac0d2661..dbce3cca94cb 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -77,7 +77,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, * - softirq stack * - hardirq stack */ - for (regs = NULL; stack; stack = stack_info.next_sp) { + for (regs = NULL; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { const char *stack_name; /* @@ -289,9 +289,6 @@ void die(const char *str, struct pt_regs *regs, long err) unsigned long flags = oops_begin(); int sig = SIGSEGV; - if (!user_mode(regs)) - report_bug(regs->ip, regs); - if (__die(str, regs, err)) sig = 0; oops_end(flags, regs, sig); diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index b0b3a3df7c20..e5f0b40e66d2 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -162,15 +162,3 @@ void show_regs(struct pt_regs *regs) } pr_cont("\n"); } - -int is_valid_bugaddr(unsigned long ip) -{ - unsigned short ud2; - - if (ip < PAGE_OFFSET) - return 0; - if (probe_kernel_address((unsigned short *)ip, ud2)) - return 0; - - return ud2 == 0x0b0f; -} diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index a8b117e93b46..3e1471d57487 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -178,13 +178,3 @@ void show_regs(struct pt_regs *regs) } pr_cont("\n"); } - -int is_valid_bugaddr(unsigned long ip) -{ - unsigned short ud2; - - if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2))) - return 0; - - return ud2 == 0x0b0f; -} diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index b2bbad6ebe4d..d78a586ba8dc 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1,49 +1,55 @@ /* - * Handle the memory map. - * The functions here do the job until bootmem takes over. + * Low level x86 E820 memory map handling functions. * - * Getting sanitize_e820_map() in sync with i386 version by applying change: - * - Provisions for empty E820 memory regions (reported by certain BIOSes). - * Alex Achenbach <xela@slit.de>, December 2002. - * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * The firmware and bootloader passes us the "E820 table", which is the primary + * physical memory layout description available about x86 systems. * + * The kernel takes the E820 memory layout and optionally modifies it with + * quirks and other tweaks, and feeds that into the generic Linux memory + * allocation code routines via a platform independent interface (memblock, etc.). */ -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/init.h> #include <linux/crash_dump.h> -#include <linux/export.h> #include <linux/bootmem.h> -#include <linux/pfn.h> #include <linux/suspend.h> #include <linux/acpi.h> #include <linux/firmware-map.h> #include <linux/memblock.h> #include <linux/sort.h> -#include <asm/e820.h> -#include <asm/proto.h> +#include <asm/e820/api.h> #include <asm/setup.h> -#include <asm/cpufeature.h> /* - * The e820 map is the map that gets modified e.g. with command line parameters - * and that is also registered with modifications in the kernel resource tree - * with the iomem_resource as parent. + * We organize the E820 table into two main data structures: * - * The e820_saved is directly saved after the BIOS-provided memory map is - * copied. It doesn't get modified afterwards. It's registered for the - * /sys/firmware/memmap interface. + * - 'e820_table_firmware': the original firmware version passed to us by the + * bootloader - not modified by the kernel. We use this to: * - * That memory map is not modified and is used as base for kexec. The kexec'd - * kernel should get the same memory map as the firmware provides. Then the - * user can e.g. boot the original kernel with mem=1G while still booting the - * next kernel with full memory. + * - inform the user about the firmware's notion of memory layout + * via /sys/firmware/memmap + * + * - the hibernation code uses it to generate a kernel-independent MD5 + * fingerprint of the physical memory layout of a system. + * + * - kexec, which is a bootloader in disguise, uses the original E820 + * layout to pass to the kexec-ed kernel. This way the original kernel + * can have a restricted E820 map while the kexec()-ed kexec-kernel + * can have access to full memory - etc. + * + * - 'e820_table': this is the main E820 table that is massaged by the + * low level x86 platform code, or modified by boot parameters, before + * passed on to higher level MM layers. + * + * Once the E820 map has been converted to the standard Linux memory layout + * information its role stops - modifying it has no effect and does not get + * re-propagated. So itsmain role is a temporary bootstrap storage of firmware + * specific memory layout data during early bootup. */ -static struct e820map initial_e820 __initdata; -static struct e820map initial_e820_saved __initdata; -struct e820map *e820 __refdata = &initial_e820; -struct e820map *e820_saved __refdata = &initial_e820_saved; +static struct e820_table e820_table_init __initdata; +static struct e820_table e820_table_firmware_init __initdata; + +struct e820_table *e820_table __refdata = &e820_table_init; +struct e820_table *e820_table_firmware __refdata = &e820_table_firmware_init; /* For PCI or other memory-mapped resources */ unsigned long pci_mem_start = 0xaeedbabe; @@ -55,51 +61,53 @@ EXPORT_SYMBOL(pci_mem_start); * This function checks if any part of the range <start,end> is mapped * with type. */ -int -e820_any_mapped(u64 start, u64 end, unsigned type) +bool e820__mapped_any(u64 start, u64 end, enum e820_type type) { int i; - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; - if (type && ei->type != type) + if (type && entry->type != type) continue; - if (ei->addr >= end || ei->addr + ei->size <= start) + if (entry->addr >= end || entry->addr + entry->size <= start) continue; return 1; } return 0; } -EXPORT_SYMBOL_GPL(e820_any_mapped); +EXPORT_SYMBOL_GPL(e820__mapped_any); /* - * This function checks if the entire range <start,end> is mapped with type. + * This function checks if the entire <start,end> range is mapped with 'type'. * - * Note: this function only works correct if the e820 table is sorted and - * not-overlapping, which is the case + * Note: this function only works correctly once the E820 table is sorted and + * not-overlapping (at least for the range specified), which is the case normally. */ -int __init e820_all_mapped(u64 start, u64 end, unsigned type) +bool __init e820__mapped_all(u64 start, u64 end, enum e820_type type) { int i; - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; - if (type && ei->type != type) + if (type && entry->type != type) continue; - /* is the region (part) in overlap with the current region ?*/ - if (ei->addr >= end || ei->addr + ei->size <= start) + + /* Is the region (part) in overlap with the current region? */ + if (entry->addr >= end || entry->addr + entry->size <= start) continue; - /* if the region is at the beginning of <start,end> we move - * start to the end of the region since it's ok until there + /* + * If the region is at the beginning of <start,end> we move + * 'start' to the end of the region since it's ok until there */ - if (ei->addr <= start) - start = ei->addr + ei->size; + if (entry->addr <= start) + start = entry->addr + entry->size; + /* - * if start is now at or beyond end, we're done, full - * coverage + * If 'start' is now at or beyond 'end', we're done, full + * coverage of the desired range exists: */ if (start >= end) return 1; @@ -108,94 +116,77 @@ int __init e820_all_mapped(u64 start, u64 end, unsigned type) } /* - * Add a memory region to the kernel e820 map. + * Add a memory region to the kernel E820 map. */ -static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size, - int type) +static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type) { - int x = e820x->nr_map; + int x = table->nr_entries; - if (x >= ARRAY_SIZE(e820x->map)) { - printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n", - (unsigned long long) start, - (unsigned long long) (start + size - 1)); + if (x >= ARRAY_SIZE(table->entries)) { + pr_err("e820: too many entries; ignoring [mem %#010llx-%#010llx]\n", start, start + size - 1); return; } - e820x->map[x].addr = start; - e820x->map[x].size = size; - e820x->map[x].type = type; - e820x->nr_map++; + table->entries[x].addr = start; + table->entries[x].size = size; + table->entries[x].type = type; + table->nr_entries++; } -void __init e820_add_region(u64 start, u64 size, int type) +void __init e820__range_add(u64 start, u64 size, enum e820_type type) { - __e820_add_region(e820, start, size, type); + __e820__range_add(e820_table, start, size, type); } -static void __init e820_print_type(u32 type) +static void __init e820_print_type(enum e820_type type) { switch (type) { - case E820_RAM: - case E820_RESERVED_KERN: - printk(KERN_CONT "usable"); - break; - case E820_RESERVED: - printk(KERN_CONT "reserved"); - break; - case E820_ACPI: - printk(KERN_CONT "ACPI data"); - break; - case E820_NVS: - printk(KERN_CONT "ACPI NVS"); - break; - case E820_UNUSABLE: - printk(KERN_CONT "unusable"); - break; - case E820_PMEM: - case E820_PRAM: - printk(KERN_CONT "persistent (type %u)", type); - break; - default: - printk(KERN_CONT "type %u", type); - break; + case E820_TYPE_RAM: /* Fall through: */ + case E820_TYPE_RESERVED_KERN: pr_cont("usable"); break; + case E820_TYPE_RESERVED: pr_cont("reserved"); break; + case E820_TYPE_ACPI: pr_cont("ACPI data"); break; + case E820_TYPE_NVS: pr_cont("ACPI NVS"); break; + case E820_TYPE_UNUSABLE: pr_cont("unusable"); break; + case E820_TYPE_PMEM: /* Fall through: */ + case E820_TYPE_PRAM: pr_cont("persistent (type %u)", type); break; + default: pr_cont("type %u", type); break; } } -void __init e820_print_map(char *who) +void __init e820__print_table(char *who) { int i; - for (i = 0; i < e820->nr_map; i++) { - printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who, - (unsigned long long) e820->map[i].addr, - (unsigned long long) - (e820->map[i].addr + e820->map[i].size - 1)); - e820_print_type(e820->map[i].type); - printk(KERN_CONT "\n"); + for (i = 0; i < e820_table->nr_entries; i++) { + pr_info("%s: [mem %#018Lx-%#018Lx] ", who, + e820_table->entries[i].addr, + e820_table->entries[i].addr + e820_table->entries[i].size - 1); + + e820_print_type(e820_table->entries[i].type); + pr_cont("\n"); } } /* - * Sanitize the BIOS e820 map. + * Sanitize an E820 map. * - * Some e820 responses include overlapping entries. The following - * replaces the original e820 map with a new one, removing overlaps, + * Some E820 layouts include overlapping entries. The following + * replaces the original E820 map with a new one, removing overlaps, * and resolving conflicting memory types in favor of highest * numbered type. * - * The input parameter biosmap points to an array of 'struct - * e820entry' which on entry has elements in the range [0, *pnr_map) - * valid, and which has space for up to max_nr_map entries. - * On return, the resulting sanitized e820 map entries will be in - * overwritten in the same location, starting at biosmap. + * The input parameter 'entries' points to an array of 'struct + * e820_entry' which on entry has elements in the range [0, *nr_entries) + * valid, and which has space for up to max_nr_entries entries. + * On return, the resulting sanitized E820 map entries will be in + * overwritten in the same location, starting at 'entries'. * - * The integer pointed to by pnr_map must be valid on entry (the - * current number of valid entries located at biosmap). If the - * sanitizing succeeds the *pnr_map will be updated with the new - * number of valid entries (something no more than max_nr_map). + * The integer pointed to by nr_entries must be valid on entry (the + * current number of valid entries located at 'entries'). If the + * sanitizing succeeds the *nr_entries will be updated with the new + * number of valid entries (something no more than max_nr_entries). * - * The return value from sanitize_e820_map() is zero if it + * The return value from e820__update_table() is zero if it * successfully 'sanitized' the map entries passed in, and is -1 * if it did nothing, which can happen if either of (1) it was * only passed one map entry, or (2) any of the input map entries @@ -238,10 +229,17 @@ void __init e820_print_map(char *who) * ______________________4_ */ struct change_member { - struct e820entry *pbios; /* pointer to original bios entry */ - unsigned long long addr; /* address for this change point */ + /* Pointer to the original entry: */ + struct e820_entry *entry; + /* Address for this change point: */ + unsigned long long addr; }; +static struct change_member change_point_list[2*E820_MAX_ENTRIES] __initdata; +static struct change_member *change_point[2*E820_MAX_ENTRIES] __initdata; +static struct e820_entry *overlap_list[E820_MAX_ENTRIES] __initdata; +static struct e820_entry new_entries[E820_MAX_ENTRIES] __initdata; + static int __init cpcompare(const void *a, const void *b) { struct change_member * const *app = a, * const *bpp = b; @@ -249,164 +247,140 @@ static int __init cpcompare(const void *a, const void *b) /* * Inputs are pointers to two elements of change_point[]. If their - * addresses are unequal, their difference dominates. If the addresses + * addresses are not equal, their difference dominates. If the addresses * are equal, then consider one that represents the end of its region * to be greater than one that does not. */ if (ap->addr != bp->addr) return ap->addr > bp->addr ? 1 : -1; - return (ap->addr != ap->pbios->addr) - (bp->addr != bp->pbios->addr); + return (ap->addr != ap->entry->addr) - (bp->addr != bp->entry->addr); } -int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, - u32 *pnr_map) +int __init e820__update_table(struct e820_table *table) { - static struct change_member change_point_list[2*E820_X_MAX] __initdata; - static struct change_member *change_point[2*E820_X_MAX] __initdata; - static struct e820entry *overlap_list[E820_X_MAX] __initdata; - static struct e820entry new_bios[E820_X_MAX] __initdata; - unsigned long current_type, last_type; + struct e820_entry *entries = table->entries; + u32 max_nr_entries = ARRAY_SIZE(table->entries); + enum e820_type current_type, last_type; unsigned long long last_addr; - int chgidx; - int overlap_entries; - int new_bios_entry; - int old_nr, new_nr, chg_nr; - int i; + u32 new_nr_entries, overlap_entries; + u32 i, chg_idx, chg_nr; - /* if there's only one memory region, don't bother */ - if (*pnr_map < 2) + /* If there's only one memory region, don't bother: */ + if (table->nr_entries < 2) return -1; - old_nr = *pnr_map; - BUG_ON(old_nr > max_nr_map); + BUG_ON(table->nr_entries > max_nr_entries); - /* bail out if we find any unreasonable addresses in bios map */ - for (i = 0; i < old_nr; i++) - if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) + /* Bail out if we find any unreasonable addresses in the map: */ + for (i = 0; i < table->nr_entries; i++) { + if (entries[i].addr + entries[i].size < entries[i].addr) return -1; + } - /* create pointers for initial change-point information (for sorting) */ - for (i = 0; i < 2 * old_nr; i++) + /* Create pointers for initial change-point information (for sorting): */ + for (i = 0; i < 2 * table->nr_entries; i++) change_point[i] = &change_point_list[i]; - /* record all known change-points (starting and ending addresses), - omitting those that are for empty memory regions */ - chgidx = 0; - for (i = 0; i < old_nr; i++) { - if (biosmap[i].size != 0) { - change_point[chgidx]->addr = biosmap[i].addr; - change_point[chgidx++]->pbios = &biosmap[i]; - change_point[chgidx]->addr = biosmap[i].addr + - biosmap[i].size; - change_point[chgidx++]->pbios = &biosmap[i]; + /* + * Record all known change-points (starting and ending addresses), + * omitting empty memory regions: + */ + chg_idx = 0; + for (i = 0; i < table->nr_entries; i++) { + if (entries[i].size != 0) { + change_point[chg_idx]->addr = entries[i].addr; + change_point[chg_idx++]->entry = &entries[i]; + change_point[chg_idx]->addr = entries[i].addr + entries[i].size; + change_point[chg_idx++]->entry = &entries[i]; } } - chg_nr = chgidx; - - /* sort change-point list by memory addresses (low -> high) */ - sort(change_point, chg_nr, sizeof *change_point, cpcompare, NULL); - - /* create a new bios memory map, removing overlaps */ - overlap_entries = 0; /* number of entries in the overlap table */ - new_bios_entry = 0; /* index for creating new bios map entries */ - last_type = 0; /* start with undefined memory type */ - last_addr = 0; /* start with 0 as last starting address */ - - /* loop through change-points, determining affect on the new bios map */ - for (chgidx = 0; chgidx < chg_nr; chgidx++) { - /* keep track of all overlapping bios entries */ - if (change_point[chgidx]->addr == - change_point[chgidx]->pbios->addr) { - /* - * add map entry to overlap list (> 1 entry - * implies an overlap) - */ - overlap_list[overlap_entries++] = - change_point[chgidx]->pbios; + chg_nr = chg_idx; + + /* Sort change-point list by memory addresses (low -> high): */ + sort(change_point, chg_nr, sizeof(*change_point), cpcompare, NULL); + + /* Create a new memory map, removing overlaps: */ + overlap_entries = 0; /* Number of entries in the overlap table */ + new_nr_entries = 0; /* Index for creating new map entries */ + last_type = 0; /* Start with undefined memory type */ + last_addr = 0; /* Start with 0 as last starting address */ + + /* Loop through change-points, determining effect on the new map: */ + for (chg_idx = 0; chg_idx < chg_nr; chg_idx++) { + /* Keep track of all overlapping entries */ + if (change_point[chg_idx]->addr == change_point[chg_idx]->entry->addr) { + /* Add map entry to overlap list (> 1 entry implies an overlap) */ + overlap_list[overlap_entries++] = change_point[chg_idx]->entry; } else { - /* - * remove entry from list (order independent, - * so swap with last) - */ + /* Remove entry from list (order independent, so swap with last): */ for (i = 0; i < overlap_entries; i++) { - if (overlap_list[i] == - change_point[chgidx]->pbios) - overlap_list[i] = - overlap_list[overlap_entries-1]; + if (overlap_list[i] == change_point[chg_idx]->entry) + overlap_list[i] = overlap_list[overlap_entries-1]; } overlap_entries--; } /* - * if there are overlapping entries, decide which + * If there are overlapping entries, decide which * "type" to use (larger value takes precedence -- * 1=usable, 2,3,4,4+=unusable) */ current_type = 0; - for (i = 0; i < overlap_entries; i++) + for (i = 0; i < overlap_entries; i++) { if (overlap_list[i]->type > current_type) current_type = overlap_list[i]->type; - /* - * continue building up new bios map based on this - * information - */ - if (current_type != last_type || current_type == E820_PRAM) { + } + + /* Continue building up new map based on this information: */ + if (current_type != last_type || current_type == E820_TYPE_PRAM) { if (last_type != 0) { - new_bios[new_bios_entry].size = - change_point[chgidx]->addr - last_addr; - /* - * move forward only if the new size - * was non-zero - */ - if (new_bios[new_bios_entry].size != 0) - /* - * no more space left for new - * bios entries ? - */ - if (++new_bios_entry >= max_nr_map) + new_entries[new_nr_entries].size = change_point[chg_idx]->addr - last_addr; + /* Move forward only if the new size was non-zero: */ + if (new_entries[new_nr_entries].size != 0) + /* No more space left for new entries? */ + if (++new_nr_entries >= max_nr_entries) break; } if (current_type != 0) { - new_bios[new_bios_entry].addr = - change_point[chgidx]->addr; - new_bios[new_bios_entry].type = current_type; - last_addr = change_point[chgidx]->addr; + new_entries[new_nr_entries].addr = change_point[chg_idx]->addr; + new_entries[new_nr_entries].type = current_type; + last_addr = change_point[chg_idx]->addr; } last_type = current_type; } } - /* retain count for new bios entries */ - new_nr = new_bios_entry; - /* copy new bios mapping into original location */ - memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry)); - *pnr_map = new_nr; + /* Copy the new entries into the original location: */ + memcpy(entries, new_entries, new_nr_entries*sizeof(*entries)); + table->nr_entries = new_nr_entries; return 0; } -static int __init __append_e820_map(struct e820entry *biosmap, int nr_map) +static int __init __append_e820_table(struct boot_e820_entry *entries, u32 nr_entries) { - while (nr_map) { - u64 start = biosmap->addr; - u64 size = biosmap->size; + struct boot_e820_entry *entry = entries; + + while (nr_entries) { + u64 start = entry->addr; + u64 size = entry->size; u64 end = start + size - 1; - u32 type = biosmap->type; + u32 type = entry->type; - /* Overflow in 64 bits? Ignore the memory map. */ + /* Ignore the entry on 64-bit overflow: */ if (start > end && likely(size)) return -1; - e820_add_region(start, size, type); + e820__range_add(start, size, type); - biosmap++; - nr_map--; + entry++; + nr_entries--; } return 0; } /* - * Copy the BIOS e820 map into a safe place. + * Copy the BIOS E820 map into a safe place. * * Sanity-check it while we're at it.. * @@ -414,18 +388,17 @@ static int __init __append_e820_map(struct e820entry *biosmap, int nr_map) * will have given us a memory map that we can use to properly * set up memory. If we aren't, we'll fake a memory map. */ -static int __init append_e820_map(struct e820entry *biosmap, int nr_map) +static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entries) { /* Only one memory region (or negative)? Ignore it */ - if (nr_map < 2) + if (nr_entries < 2) return -1; - return __append_e820_map(biosmap, nr_map); + return __append_e820_table(entries, nr_entries); } -static u64 __init __e820_update_range(struct e820map *e820x, u64 start, - u64 size, unsigned old_type, - unsigned new_type) +static u64 __init +__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type) { u64 end; unsigned int i; @@ -437,77 +410,73 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start, size = ULLONG_MAX - start; end = start + size; - printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", - (unsigned long long) start, (unsigned long long) (end - 1)); + printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", start, end - 1); e820_print_type(old_type); - printk(KERN_CONT " ==> "); + pr_cont(" ==> "); e820_print_type(new_type); - printk(KERN_CONT "\n"); + pr_cont("\n"); - for (i = 0; i < e820x->nr_map; i++) { - struct e820entry *ei = &e820x->map[i]; + for (i = 0; i < table->nr_entries; i++) { + struct e820_entry *entry = &table->entries[i]; u64 final_start, final_end; - u64 ei_end; + u64 entry_end; - if (ei->type != old_type) + if (entry->type != old_type) continue; - ei_end = ei->addr + ei->size; - /* totally covered by new range? */ - if (ei->addr >= start && ei_end <= end) { - ei->type = new_type; - real_updated_size += ei->size; + entry_end = entry->addr + entry->size; + + /* Completely covered by new range? */ + if (entry->addr >= start && entry_end <= end) { + entry->type = new_type; + real_updated_size += entry->size; continue; } - /* new range is totally covered? */ - if (ei->addr < start && ei_end > end) { - __e820_add_region(e820x, start, size, new_type); - __e820_add_region(e820x, end, ei_end - end, ei->type); - ei->size = start - ei->addr; + /* New range is completely covered? */ + if (entry->addr < start && entry_end > end) { + __e820__range_add(table, start, size, new_type); + __e820__range_add(table, end, entry_end - end, entry->type); + entry->size = start - entry->addr; real_updated_size += size; continue; } - /* partially covered */ - final_start = max(start, ei->addr); - final_end = min(end, ei_end); + /* Partially covered: */ + final_start = max(start, entry->addr); + final_end = min(end, entry_end); if (final_start >= final_end) continue; - __e820_add_region(e820x, final_start, final_end - final_start, - new_type); + __e820__range_add(table, final_start, final_end - final_start, new_type); real_updated_size += final_end - final_start; /* - * left range could be head or tail, so need to update - * size at first. + * Left range could be head or tail, so need to update + * its size first: */ - ei->size -= final_end - final_start; - if (ei->addr < final_start) + entry->size -= final_end - final_start; + if (entry->addr < final_start) continue; - ei->addr = final_end; + + entry->addr = final_end; } return real_updated_size; } -u64 __init e820_update_range(u64 start, u64 size, unsigned old_type, - unsigned new_type) +u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type) { - return __e820_update_range(e820, start, size, old_type, new_type); + return __e820__range_update(e820_table, start, size, old_type, new_type); } -static u64 __init e820_update_range_saved(u64 start, u64 size, - unsigned old_type, unsigned new_type) +static u64 __init e820__range_update_firmware(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type) { - return __e820_update_range(e820_saved, start, size, old_type, - new_type); + return __e820__range_update(e820_table_firmware, start, size, old_type, new_type); } -/* make e820 not cover the range */ -u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type, - int checktype) +/* Remove a range of memory from the E820 table: */ +u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type) { int i; u64 end; @@ -517,85 +486,89 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type, size = ULLONG_MAX - start; end = start + size; - printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", - (unsigned long long) start, (unsigned long long) (end - 1)); - if (checktype) + printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", start, end - 1); + if (check_type) e820_print_type(old_type); - printk(KERN_CONT "\n"); + pr_cont("\n"); - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; u64 final_start, final_end; - u64 ei_end; + u64 entry_end; - if (checktype && ei->type != old_type) + if (check_type && entry->type != old_type) continue; - ei_end = ei->addr + ei->size; - /* totally covered? */ - if (ei->addr >= start && ei_end <= end) { - real_removed_size += ei->size; - memset(ei, 0, sizeof(struct e820entry)); + entry_end = entry->addr + entry->size; + + /* Completely covered? */ + if (entry->addr >= start && entry_end <= end) { + real_removed_size += entry->size; + memset(entry, 0, sizeof(*entry)); continue; } - /* new range is totally covered? */ - if (ei->addr < start && ei_end > end) { - e820_add_region(end, ei_end - end, ei->type); - ei->size = start - ei->addr; + /* Is the new range completely covered? */ + if (entry->addr < start && entry_end > end) { + e820__range_add(end, entry_end - end, entry->type); + entry->size = start - entry->addr; real_removed_size += size; continue; } - /* partially covered */ - final_start = max(start, ei->addr); - final_end = min(end, ei_end); + /* Partially covered: */ + final_start = max(start, entry->addr); + final_end = min(end, entry_end); if (final_start >= final_end) continue; + real_removed_size += final_end - final_start; /* - * left range could be head or tail, so need to update - * size at first. + * Left range could be head or tail, so need to update + * the size first: */ - ei->size -= final_end - final_start; - if (ei->addr < final_start) + entry->size -= final_end - final_start; + if (entry->addr < final_start) continue; - ei->addr = final_end; + + entry->addr = final_end; } return real_removed_size; } -void __init update_e820(void) +void __init e820__update_table_print(void) { - if (sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map)) + if (e820__update_table(e820_table)) return; - printk(KERN_INFO "e820: modified physical RAM map:\n"); - e820_print_map("modified"); + + pr_info("e820: modified physical RAM map:\n"); + e820__print_table("modified"); } -static void __init update_e820_saved(void) + +static void __init e820__update_table_firmware(void) { - sanitize_e820_map(e820_saved->map, ARRAY_SIZE(e820_saved->map), - &e820_saved->nr_map); + e820__update_table(e820_table_firmware); } + #define MAX_GAP_END 0x100000000ull + /* - * Search for a gap in the e820 memory space from 0 to MAX_GAP_END. + * Search for a gap in the E820 memory space from 0 to MAX_GAP_END (4GB). */ -static int __init e820_search_gap(unsigned long *gapstart, - unsigned long *gapsize) +static int __init e820_search_gap(unsigned long *gapstart, unsigned long *gapsize) { unsigned long long last = MAX_GAP_END; - int i = e820->nr_map; + int i = e820_table->nr_entries; int found = 0; while (--i >= 0) { - unsigned long long start = e820->map[i].addr; - unsigned long long end = start + e820->map[i].size; + unsigned long long start = e820_table->entries[i].addr; + unsigned long long end = start + e820_table->entries[i].size; /* * Since "last" is at most 4GB, we know we'll - * fit in 32 bits if this condition is true + * fit in 32 bits if this condition is true: */ if (last > end) { unsigned long gap = last - end; @@ -613,12 +586,14 @@ static int __init e820_search_gap(unsigned long *gapstart, } /* - * Search for the biggest gap in the low 32 bits of the e820 - * memory space. We pass this space to PCI to assign MMIO resources - * for hotplug or unconfigured devices in. + * Search for the biggest gap in the low 32 bits of the E820 + * memory space. We pass this space to the PCI subsystem, so + * that it can assign MMIO resources for hotplug or + * unconfigured devices in. + * * Hopefully the BIOS let enough space left. */ -__init void e820_setup_gap(void) +__init void e820__setup_pci_gap(void) { unsigned long gapstart, gapsize; int found; @@ -629,138 +604,143 @@ __init void e820_setup_gap(void) if (!found) { #ifdef CONFIG_X86_64 gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024; - printk(KERN_ERR - "e820: cannot find a gap in the 32bit address range\n" - "e820: PCI devices with unassigned 32bit BARs may break!\n"); + pr_err( + "e820: Cannot find an available gap in the 32-bit address range\n" + "e820: PCI devices with unassigned 32-bit BARs may not work!\n"); #else gapstart = 0x10000000; #endif } /* - * e820_reserve_resources_late protect stolen RAM already + * e820__reserve_resources_late() protects stolen RAM already: */ pci_mem_start = gapstart; - printk(KERN_INFO - "e820: [mem %#010lx-%#010lx] available for PCI devices\n", - gapstart, gapstart + gapsize - 1); + pr_info("e820: [mem %#010lx-%#010lx] available for PCI devices\n", gapstart, gapstart + gapsize - 1); } /* * Called late during init, in free_initmem(). * - * Initial e820 and e820_saved are largish __initdata arrays. - * Copy them to (usually much smaller) dynamically allocated area. - * This is done after all tweaks we ever do to them: - * all functions which modify them are __init functions, - * they won't exist after this point. + * Initial e820_table and e820_table_firmware are largish __initdata arrays. + * + * Copy them to a (usually much smaller) dynamically allocated area that is + * sized precisely after the number of e820 entries. + * + * This is done after we've performed all the fixes and tweaks to the tables. + * All functions which modify them are __init functions, which won't exist + * after free_initmem(). */ -__init void e820_reallocate_tables(void) +__init void e820__reallocate_tables(void) { - struct e820map *n; + struct e820_table *n; int size; - size = offsetof(struct e820map, map) + sizeof(struct e820entry) * e820->nr_map; + size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table->nr_entries; n = kmalloc(size, GFP_KERNEL); BUG_ON(!n); - memcpy(n, e820, size); - e820 = n; + memcpy(n, e820_table, size); + e820_table = n; - size = offsetof(struct e820map, map) + sizeof(struct e820entry) * e820_saved->nr_map; + size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_firmware->nr_entries; n = kmalloc(size, GFP_KERNEL); BUG_ON(!n); - memcpy(n, e820_saved, size); - e820_saved = n; + memcpy(n, e820_table_firmware, size); + e820_table_firmware = n; } -/** - * Because of the size limitation of struct boot_params, only first - * 128 E820 memory entries are passed to kernel via - * boot_params.e820_map, others are passed via SETUP_E820_EXT node of - * linked list of struct setup_data, which is parsed here. +/* + * Because of the small fixed size of struct boot_params, only the first + * 128 E820 memory entries are passed to the kernel via boot_params.e820_table, + * the remaining (if any) entries are passed via the SETUP_E820_EXT node of + * struct setup_data, which is parsed here. */ -void __init parse_e820_ext(u64 phys_addr, u32 data_len) +void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len) { int entries; - struct e820entry *extmap; + struct boot_e820_entry *extmap; struct setup_data *sdata; sdata = early_memremap(phys_addr, data_len); - entries = sdata->len / sizeof(struct e820entry); - extmap = (struct e820entry *)(sdata->data); - __append_e820_map(extmap, entries); - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); + entries = sdata->len / sizeof(*extmap); + extmap = (struct boot_e820_entry *)(sdata->data); + + __append_e820_table(extmap, entries); + e820__update_table(e820_table); + early_memunmap(sdata, data_len); - printk(KERN_INFO "e820: extended physical RAM map:\n"); - e820_print_map("extended"); + pr_info("e820: extended physical RAM map:\n"); + e820__print_table("extended"); } -#if defined(CONFIG_X86_64) || \ - (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) -/** +/* * Find the ranges of physical addresses that do not correspond to - * e820 RAM areas and mark the corresponding pages as nosave for - * hibernation (32 bit) or software suspend and suspend to RAM (64 bit). + * E820 RAM areas and register the corresponding pages as 'nosave' for + * hibernation (32-bit) or software suspend and suspend to RAM (64-bit). * - * This function requires the e820 map to be sorted and without any + * This function requires the E820 map to be sorted and without any * overlapping entries. */ -void __init e820_mark_nosave_regions(unsigned long limit_pfn) +void __init e820__register_nosave_regions(unsigned long limit_pfn) { int i; unsigned long pfn = 0; - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; - if (pfn < PFN_UP(ei->addr)) - register_nosave_region(pfn, PFN_UP(ei->addr)); + if (pfn < PFN_UP(entry->addr)) + register_nosave_region(pfn, PFN_UP(entry->addr)); - pfn = PFN_DOWN(ei->addr + ei->size); + pfn = PFN_DOWN(entry->addr + entry->size); - if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN) - register_nosave_region(PFN_UP(ei->addr), pfn); + if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN) + register_nosave_region(PFN_UP(entry->addr), pfn); if (pfn >= limit_pfn) break; } } -#endif #ifdef CONFIG_ACPI -/** - * Mark ACPI NVS memory region, so that we can save/restore it during - * hibernation and the subsequent resume. +/* + * Register ACPI NVS memory regions, so that we can save/restore them during + * hibernation and the subsequent resume: */ -static int __init e820_mark_nvs_memory(void) +static int __init e820__register_nvs_regions(void) { int i; - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; - if (ei->type == E820_NVS) - acpi_nvs_register(ei->addr, ei->size); + if (entry->type == E820_TYPE_NVS) + acpi_nvs_register(entry->addr, entry->size); } return 0; } -core_initcall(e820_mark_nvs_memory); +core_initcall(e820__register_nvs_regions); #endif /* - * pre allocated 4k and reserved it in memblock and e820_saved + * Allocate the requested number of bytes with the requsted alignment + * and return (the physical address) to the caller. Also register this + * range in the 'firmware' E820 table as a reserved range. + * + * This allows kexec to fake a new mptable, as if it came from the real + * system. */ -u64 __init early_reserve_e820(u64 size, u64 align) +u64 __init e820__memblock_alloc_reserved(u64 size, u64 align) { u64 addr; addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); if (addr) { - e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED); - printk(KERN_INFO "e820: update e820_saved for early_reserve_e820\n"); - update_e820_saved(); + e820__range_update_firmware(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED); + pr_info("e820: update e820_table_firmware for e820__memblock_alloc_reserved()\n"); + e820__update_table_firmware(); } return addr; @@ -779,22 +759,22 @@ u64 __init early_reserve_e820(u64 size, u64 align) /* * Find the highest page frame number we have available */ -static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) +static unsigned long __init e820_end_pfn(unsigned long limit_pfn, enum e820_type type) { int i; unsigned long last_pfn = 0; unsigned long max_arch_pfn = MAX_ARCH_PFN; - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; unsigned long start_pfn; unsigned long end_pfn; - if (ei->type != type) + if (entry->type != type) continue; - start_pfn = ei->addr >> PAGE_SHIFT; - end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT; + start_pfn = entry->addr >> PAGE_SHIFT; + end_pfn = (entry->addr + entry->size) >> PAGE_SHIFT; if (start_pfn >= limit_pfn) continue; @@ -809,18 +789,19 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) if (last_pfn > max_arch_pfn) last_pfn = max_arch_pfn; - printk(KERN_INFO "e820: last_pfn = %#lx max_arch_pfn = %#lx\n", + pr_info("e820: last_pfn = %#lx max_arch_pfn = %#lx\n", last_pfn, max_arch_pfn); return last_pfn; } -unsigned long __init e820_end_of_ram_pfn(void) + +unsigned long __init e820__end_of_ram_pfn(void) { - return e820_end_pfn(MAX_ARCH_PFN, E820_RAM); + return e820_end_pfn(MAX_ARCH_PFN, E820_TYPE_RAM); } -unsigned long __init e820_end_of_low_ram_pfn(void) +unsigned long __init e820__end_of_low_ram_pfn(void) { - return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_RAM); + return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_TYPE_RAM); } static void __init early_panic(char *msg) @@ -831,7 +812,7 @@ static void __init early_panic(char *msg) static int userdef __initdata; -/* "mem=nopentium" disables the 4MB page tables. */ +/* The "mem=nopentium" boot option disables 4MB page tables on 32-bit kernels: */ static int __init parse_memopt(char *p) { u64 mem_size; @@ -844,17 +825,19 @@ static int __init parse_memopt(char *p) setup_clear_cpu_cap(X86_FEATURE_PSE); return 0; #else - printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n"); + pr_warn("mem=nopentium ignored! (only supported on x86_32)\n"); return -EINVAL; #endif } userdef = 1; mem_size = memparse(p, &p); - /* don't remove all of memory when handling "mem={invalid}" param */ + + /* Don't remove all memory when getting "mem={invalid}" parameter: */ if (mem_size == 0) return -EINVAL; - e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1); + + e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1); return 0; } @@ -872,12 +855,12 @@ static int __init parse_memmap_one(char *p) #ifdef CONFIG_CRASH_DUMP /* * If we are doing a crash dump, we still need to know - * the real mem size before original memory map is + * the real memory size before the original memory map is * reset. */ - saved_max_pfn = e820_end_of_ram_pfn(); + saved_max_pfn = e820__end_of_ram_pfn(); #endif - e820->nr_map = 0; + e820_table->nr_entries = 0; userdef = 1; return 0; } @@ -890,21 +873,23 @@ static int __init parse_memmap_one(char *p) userdef = 1; if (*p == '@') { start_at = memparse(p+1, &p); - e820_add_region(start_at, mem_size, E820_RAM); + e820__range_add(start_at, mem_size, E820_TYPE_RAM); } else if (*p == '#') { start_at = memparse(p+1, &p); - e820_add_region(start_at, mem_size, E820_ACPI); + e820__range_add(start_at, mem_size, E820_TYPE_ACPI); } else if (*p == '$') { start_at = memparse(p+1, &p); - e820_add_region(start_at, mem_size, E820_RESERVED); + e820__range_add(start_at, mem_size, E820_TYPE_RESERVED); } else if (*p == '!') { start_at = memparse(p+1, &p); - e820_add_region(start_at, mem_size, E820_PRAM); - } else - e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1); + e820__range_add(start_at, mem_size, E820_TYPE_PRAM); + } else { + e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1); + } return *p == '\0' ? 0 : -EINVAL; } + static int __init parse_memmap_opt(char *str) { while (str) { @@ -921,68 +906,97 @@ static int __init parse_memmap_opt(char *str) } early_param("memmap", parse_memmap_opt); -void __init finish_e820_parsing(void) +/* + * Reserve all entries from the bootloader's extensible data nodes list, + * because if present we are going to use it later on to fetch e820 + * entries from it: + */ +void __init e820__reserve_setup_data(void) +{ + struct setup_data *data; + u64 pa_data; + + pa_data = boot_params.hdr.setup_data; + if (!pa_data) + return; + + while (pa_data) { + data = early_memremap(pa_data, sizeof(*data)); + e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); + pa_data = data->next; + early_memunmap(data, sizeof(*data)); + } + + e820__update_table(e820_table); + + memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware)); + + pr_info("extended physical RAM map:\n"); + e820__print_table("reserve setup_data"); +} + +/* + * Called after parse_early_param(), after early parameters (such as mem=) + * have been processed, in which case we already have an E820 table filled in + * via the parameter callback function(s), but it's not sorted and printed yet: + */ +void __init e820__finish_early_params(void) { if (userdef) { - if (sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), - &e820->nr_map) < 0) + if (e820__update_table(e820_table) < 0) early_panic("Invalid user supplied memory map"); - printk(KERN_INFO "e820: user-defined physical RAM map:\n"); - e820_print_map("user"); + pr_info("e820: user-defined physical RAM map:\n"); + e820__print_table("user"); } } -static const char *__init e820_type_to_string(int e820_type) +static const char *__init e820_type_to_string(struct e820_entry *entry) { - switch (e820_type) { - case E820_RESERVED_KERN: - case E820_RAM: return "System RAM"; - case E820_ACPI: return "ACPI Tables"; - case E820_NVS: return "ACPI Non-volatile Storage"; - case E820_UNUSABLE: return "Unusable memory"; - case E820_PRAM: return "Persistent Memory (legacy)"; - case E820_PMEM: return "Persistent Memory"; - default: return "reserved"; + switch (entry->type) { + case E820_TYPE_RESERVED_KERN: /* Fall-through: */ + case E820_TYPE_RAM: return "System RAM"; + case E820_TYPE_ACPI: return "ACPI Tables"; + case E820_TYPE_NVS: return "ACPI Non-volatile Storage"; + case E820_TYPE_UNUSABLE: return "Unusable memory"; + case E820_TYPE_PRAM: return "Persistent Memory (legacy)"; + case E820_TYPE_PMEM: return "Persistent Memory"; + case E820_TYPE_RESERVED: return "Reserved"; + default: return "Unknown E820 type"; } } -static unsigned long __init e820_type_to_iomem_type(int e820_type) +static unsigned long __init e820_type_to_iomem_type(struct e820_entry *entry) { - switch (e820_type) { - case E820_RESERVED_KERN: - case E820_RAM: - return IORESOURCE_SYSTEM_RAM; - case E820_ACPI: - case E820_NVS: - case E820_UNUSABLE: - case E820_PRAM: - case E820_PMEM: - default: - return IORESOURCE_MEM; + switch (entry->type) { + case E820_TYPE_RESERVED_KERN: /* Fall-through: */ + case E820_TYPE_RAM: return IORESOURCE_SYSTEM_RAM; + case E820_TYPE_ACPI: /* Fall-through: */ + case E820_TYPE_NVS: /* Fall-through: */ + case E820_TYPE_UNUSABLE: /* Fall-through: */ + case E820_TYPE_PRAM: /* Fall-through: */ + case E820_TYPE_PMEM: /* Fall-through: */ + case E820_TYPE_RESERVED: /* Fall-through: */ + default: return IORESOURCE_MEM; } } -static unsigned long __init e820_type_to_iores_desc(int e820_type) +static unsigned long __init e820_type_to_iores_desc(struct e820_entry *entry) { - switch (e820_type) { - case E820_ACPI: - return IORES_DESC_ACPI_TABLES; - case E820_NVS: - return IORES_DESC_ACPI_NV_STORAGE; - case E820_PMEM: - return IORES_DESC_PERSISTENT_MEMORY; - case E820_PRAM: - return IORES_DESC_PERSISTENT_MEMORY_LEGACY; - case E820_RESERVED_KERN: - case E820_RAM: - case E820_UNUSABLE: - default: - return IORES_DESC_NONE; + switch (entry->type) { + case E820_TYPE_ACPI: return IORES_DESC_ACPI_TABLES; + case E820_TYPE_NVS: return IORES_DESC_ACPI_NV_STORAGE; + case E820_TYPE_PMEM: return IORES_DESC_PERSISTENT_MEMORY; + case E820_TYPE_PRAM: return IORES_DESC_PERSISTENT_MEMORY_LEGACY; + case E820_TYPE_RESERVED_KERN: /* Fall-through: */ + case E820_TYPE_RAM: /* Fall-through: */ + case E820_TYPE_UNUSABLE: /* Fall-through: */ + case E820_TYPE_RESERVED: /* Fall-through: */ + default: return IORES_DESC_NONE; } } -static bool __init do_mark_busy(u32 type, struct resource *res) +static bool __init do_mark_busy(enum e820_type type, struct resource *res) { /* this is the legacy bios/dos rom-shadow + mmio region */ if (res->start < (1ULL<<20)) @@ -993,61 +1007,71 @@ static bool __init do_mark_busy(u32 type, struct resource *res) * for exclusive use of a driver */ switch (type) { - case E820_RESERVED: - case E820_PRAM: - case E820_PMEM: + case E820_TYPE_RESERVED: + case E820_TYPE_PRAM: + case E820_TYPE_PMEM: return false; + case E820_TYPE_RESERVED_KERN: + case E820_TYPE_RAM: + case E820_TYPE_ACPI: + case E820_TYPE_NVS: + case E820_TYPE_UNUSABLE: default: return true; } } /* - * Mark e820 reserved areas as busy for the resource manager. + * Mark E820 reserved areas as busy for the resource manager: */ + static struct resource __initdata *e820_res; -void __init e820_reserve_resources(void) + +void __init e820__reserve_resources(void) { int i; struct resource *res; u64 end; - res = alloc_bootmem(sizeof(struct resource) * e820->nr_map); + res = alloc_bootmem(sizeof(*res) * e820_table->nr_entries); e820_res = res; - for (i = 0; i < e820->nr_map; i++) { - end = e820->map[i].addr + e820->map[i].size - 1; + + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = e820_table->entries + i; + + end = entry->addr + entry->size - 1; if (end != (resource_size_t)end) { res++; continue; } - res->name = e820_type_to_string(e820->map[i].type); - res->start = e820->map[i].addr; - res->end = end; - - res->flags = e820_type_to_iomem_type(e820->map[i].type); - res->desc = e820_type_to_iores_desc(e820->map[i].type); + res->start = entry->addr; + res->end = end; + res->name = e820_type_to_string(entry); + res->flags = e820_type_to_iomem_type(entry); + res->desc = e820_type_to_iores_desc(entry); /* - * don't register the region that could be conflicted with - * pci device BAR resource and insert them later in - * pcibios_resource_survey() + * Don't register the region that could be conflicted with + * PCI device BAR resources and insert them later in + * pcibios_resource_survey(): */ - if (do_mark_busy(e820->map[i].type, res)) { + if (do_mark_busy(entry->type, res)) { res->flags |= IORESOURCE_BUSY; insert_resource(&iomem_resource, res); } res++; } - for (i = 0; i < e820_saved->nr_map; i++) { - struct e820entry *entry = &e820_saved->map[i]; - firmware_map_add_early(entry->addr, - entry->addr + entry->size, - e820_type_to_string(entry->type)); + for (i = 0; i < e820_table_firmware->nr_entries; i++) { + struct e820_entry *entry = e820_table_firmware->entries + i; + + firmware_map_add_early(entry->addr, entry->addr + entry->size, e820_type_to_string(entry)); } } -/* How much should we pad RAM ending depending on where it is? */ +/* + * How much should we pad the end of RAM, depending on where it is? + */ static unsigned long __init ram_alignment(resource_size_t pos) { unsigned long mb = pos >> 20; @@ -1066,64 +1090,59 @@ static unsigned long __init ram_alignment(resource_size_t pos) #define MAX_RESOURCE_SIZE ((resource_size_t)-1) -void __init e820_reserve_resources_late(void) +void __init e820__reserve_resources_late(void) { int i; struct resource *res; res = e820_res; - for (i = 0; i < e820->nr_map; i++) { + for (i = 0; i < e820_table->nr_entries; i++) { if (!res->parent && res->end) insert_resource_expand_to_fit(&iomem_resource, res); res++; } /* - * Try to bump up RAM regions to reasonable boundaries to + * Try to bump up RAM regions to reasonable boundaries, to * avoid stolen RAM: */ - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *entry = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; u64 start, end; - if (entry->type != E820_RAM) + if (entry->type != E820_TYPE_RAM) continue; + start = entry->addr + entry->size; end = round_up(start, ram_alignment(start)) - 1; if (end > MAX_RESOURCE_SIZE) end = MAX_RESOURCE_SIZE; if (start >= end) continue; - printk(KERN_DEBUG - "e820: reserve RAM buffer [mem %#010llx-%#010llx]\n", - start, end); - reserve_region_with_split(&iomem_resource, start, end, - "RAM buffer"); + + printk(KERN_DEBUG "e820: reserve RAM buffer [mem %#010llx-%#010llx]\n", start, end); + reserve_region_with_split(&iomem_resource, start, end, "RAM buffer"); } } -char *__init default_machine_specific_memory_setup(void) +/* + * Pass the firmware (bootloader) E820 map to the kernel and process it: + */ +char *__init e820__memory_setup_default(void) { char *who = "BIOS-e820"; - u32 new_nr; + /* * Try to copy the BIOS-supplied E820-map. * * Otherwise fake a memory map; one section from 0k->640k, * the next section from 1mb->appropriate_mem_k */ - new_nr = boot_params.e820_entries; - sanitize_e820_map(boot_params.e820_map, - ARRAY_SIZE(boot_params.e820_map), - &new_nr); - boot_params.e820_entries = new_nr; - if (append_e820_map(boot_params.e820_map, boot_params.e820_entries) - < 0) { + if (append_e820_table(boot_params.e820_table, boot_params.e820_entries) < 0) { u64 mem_size; - /* compare results from other methods and take the greater */ - if (boot_params.alt_mem_k - < boot_params.screen_info.ext_mem_k) { + /* Compare results from other methods and take the one that gives more RAM: */ + if (boot_params.alt_mem_k < boot_params.screen_info.ext_mem_k) { mem_size = boot_params.screen_info.ext_mem_k; who = "BIOS-88"; } else { @@ -1131,84 +1150,68 @@ char *__init default_machine_specific_memory_setup(void) who = "BIOS-e801"; } - e820->nr_map = 0; - e820_add_region(0, LOWMEMSIZE(), E820_RAM); - e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM); + e820_table->nr_entries = 0; + e820__range_add(0, LOWMEMSIZE(), E820_TYPE_RAM); + e820__range_add(HIGH_MEMORY, mem_size << 10, E820_TYPE_RAM); } - /* In case someone cares... */ + /* We just appended a lot of ranges, sanitize the table: */ + e820__update_table(e820_table); + return who; } -void __init setup_memory_map(void) +/* + * Calls e820__memory_setup_default() in essence to pick up the firmware/bootloader + * E820 map - with an optional platform quirk available for virtual platforms + * to override this method of boot environment processing: + */ +void __init e820__memory_setup(void) { char *who; + /* This is a firmware interface ABI - make sure we don't break it: */ + BUILD_BUG_ON(sizeof(struct boot_e820_entry) != 20); + who = x86_init.resources.memory_setup(); - memcpy(e820_saved, e820, sizeof(struct e820map)); - printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n"); - e820_print_map(who); + + memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware)); + + pr_info("e820: BIOS-provided physical RAM map:\n"); + e820__print_table(who); } -void __init memblock_x86_fill(void) +void __init e820__memblock_setup(void) { int i; u64 end; /* - * EFI may have more than 128 entries - * We are safe to enable resizing, beause memblock_x86_fill() - * is rather later for x86 + * The bootstrap memblock region count maximum is 128 entries + * (INIT_MEMBLOCK_REGIONS), but EFI might pass us more E820 entries + * than that - so allow memblock resizing. + * + * This is safe, because this call happens pretty late during x86 setup, + * so we know about reserved memory regions already. (This is important + * so that memblock resizing does no stomp over reserved areas.) */ memblock_allow_resize(); - for (i = 0; i < e820->nr_map; i++) { - struct e820entry *ei = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + struct e820_entry *entry = &e820_table->entries[i]; - end = ei->addr + ei->size; + end = entry->addr + entry->size; if (end != (resource_size_t)end) continue; - if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN) + if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN) continue; - memblock_add(ei->addr, ei->size); + memblock_add(entry->addr, entry->size); } - /* throw away partial pages */ + /* Throw away partial pages: */ memblock_trim_memory(PAGE_SIZE); memblock_dump_all(); } - -void __init memblock_find_dma_reserve(void) -{ -#ifdef CONFIG_X86_64 - u64 nr_pages = 0, nr_free_pages = 0; - unsigned long start_pfn, end_pfn; - phys_addr_t start, end; - int i; - u64 u; - - /* - * need to find out used area below MAX_DMA_PFN - * need to use memblock to get free size in [0, MAX_DMA_PFN] - * at first, and assume boot_mem will not take below MAX_DMA_PFN - */ - for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) { - start_pfn = min(start_pfn, MAX_DMA_PFN); - end_pfn = min(end_pfn, MAX_DMA_PFN); - nr_pages += end_pfn - start_pfn; - } - - for_each_free_mem_range(u, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, - NULL) { - start_pfn = min_t(unsigned long, PFN_UP(start), MAX_DMA_PFN); - end_pfn = min_t(unsigned long, PFN_DOWN(end), MAX_DMA_PFN); - if (start_pfn < end_pfn) - nr_free_pages += end_pfn - start_pfn; - } - - set_dma_reserve(nr_pages - nr_free_pages); -#endif -} diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 6a08e25a48d8..ff7e4b3988ed 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -546,8 +546,8 @@ intel_graphics_stolen(int num, int slot, int func, &base, &end); /* Mark this space as reserved */ - e820_add_region(base, size, E820_RESERVED); - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); + e820__range_add(base, size, E820_TYPE_RESERVED); + e820__update_table(e820_table); } static void __init intel_graphics_quirks(int num, int slot, int func) diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 8a121991e5ba..0f0840304452 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -17,6 +17,7 @@ #include <asm/intel-mid.h> #include <asm/pgtable.h> #include <linux/usb/ehci_def.h> +#include <linux/usb/xhci-dbgp.h> #include <linux/efi.h> #include <asm/efi.h> #include <asm/pci_x86.h> @@ -381,6 +382,10 @@ static int __init setup_early_printk(char *buf) if (!strncmp(buf, "efi", 3)) early_console_register(&early_efi_console, keep); #endif +#ifdef CONFIG_EARLY_PRINTK_USB_XDBC + if (!strncmp(buf, "xdbc", 4)) + early_xdbc_parse_parameter(buf + 4); +#endif buf++; } diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c index 04f89caef9c4..8e598a1ad986 100644 --- a/arch/x86/kernel/espfix_64.c +++ b/arch/x86/kernel/espfix_64.c @@ -50,11 +50,11 @@ #define ESPFIX_STACKS_PER_PAGE (PAGE_SIZE/ESPFIX_STACK_SIZE) /* There is address space for how many espfix pages? */ -#define ESPFIX_PAGE_SPACE (1UL << (PGDIR_SHIFT-PAGE_SHIFT-16)) +#define ESPFIX_PAGE_SPACE (1UL << (P4D_SHIFT-PAGE_SHIFT-16)) #define ESPFIX_MAX_CPUS (ESPFIX_STACKS_PER_PAGE * ESPFIX_PAGE_SPACE) #if CONFIG_NR_CPUS > ESPFIX_MAX_CPUS -# error "Need more than one PGD for the ESPFIX hack" +# error "Need more virtual address space for the ESPFIX hack" #endif #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO) @@ -121,11 +121,13 @@ static void init_espfix_random(void) void __init init_espfix_bsp(void) { - pgd_t *pgd_p; + pgd_t *pgd; + p4d_t *p4d; /* Install the espfix pud into the kernel page directory */ - pgd_p = &init_level4_pgt[pgd_index(ESPFIX_BASE_ADDR)]; - pgd_populate(&init_mm, pgd_p, (pud_t *)espfix_pud_page); + pgd = &init_level4_pgt[pgd_index(ESPFIX_BASE_ADDR)]; + p4d = p4d_alloc(&init_mm, pgd, ESPFIX_BASE_ADDR); + p4d_populate(&init_mm, p4d, espfix_pud_page); /* Randomize the locations */ init_espfix_random(); diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 8639bb2ae058..5b7153540727 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -535,7 +535,7 @@ static void run_sync(void) { int enable_irqs = irqs_disabled(); - /* We may be called with interrupts disbled (on bootup). */ + /* We may be called with interrupts disabled (on bootup). */ if (enable_irqs) local_irq_enable(); on_each_cpu(do_sync_core, NULL, 1); @@ -983,6 +983,18 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent, unsigned long return_hooker = (unsigned long) &return_to_handler; + /* + * When resuming from suspend-to-ram, this function can be indirectly + * called from early CPU startup code while the CPU is in real mode, + * which would fail miserably. Make sure the stack pointer is a + * virtual address. + * + * This check isn't as accurate as virt_addr_valid(), but it should be + * good enough for this purpose, and it's fast. + */ + if (unlikely((long)__builtin_frame_address(0) >= 0)) + return; + if (unlikely(ftrace_graph_is_dead())) return; diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S new file mode 100644 index 000000000000..722a145b4139 --- /dev/null +++ b/arch/x86/kernel/ftrace_32.S @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2017 Steven Rostedt, VMware Inc. + */ + +#include <linux/linkage.h> +#include <asm/page_types.h> +#include <asm/segment.h> +#include <asm/export.h> +#include <asm/ftrace.h> + +#ifdef CC_USING_FENTRY +# define function_hook __fentry__ +EXPORT_SYMBOL(__fentry__) +#else +# define function_hook mcount +EXPORT_SYMBOL(mcount) +#endif + +#ifdef CONFIG_DYNAMIC_FTRACE + +/* mcount uses a frame pointer even if CONFIG_FRAME_POINTER is not set */ +#if !defined(CC_USING_FENTRY) || defined(CONFIG_FRAME_POINTER) +# define USING_FRAME_POINTER +#endif + +#ifdef USING_FRAME_POINTER +# define MCOUNT_FRAME 1 /* using frame = true */ +#else +# define MCOUNT_FRAME 0 /* using frame = false */ +#endif + +ENTRY(function_hook) + ret +END(function_hook) + +ENTRY(ftrace_caller) + +#ifdef USING_FRAME_POINTER +# ifdef CC_USING_FENTRY + /* + * Frame pointers are of ip followed by bp. + * Since fentry is an immediate jump, we are left with + * parent-ip, function-ip. We need to add a frame with + * parent-ip followed by ebp. + */ + pushl 4(%esp) /* parent ip */ + pushl %ebp + movl %esp, %ebp + pushl 2*4(%esp) /* function ip */ +# endif + /* For mcount, the function ip is directly above */ + pushl %ebp + movl %esp, %ebp +#endif + pushl %eax + pushl %ecx + pushl %edx + pushl $0 /* Pass NULL as regs pointer */ + +#ifdef USING_FRAME_POINTER + /* Load parent ebp into edx */ + movl 4*4(%esp), %edx +#else + /* There's no frame pointer, load the appropriate stack addr instead */ + lea 4*4(%esp), %edx +#endif + + movl (MCOUNT_FRAME+4)*4(%esp), %eax /* load the rip */ + /* Get the parent ip */ + movl 4(%edx), %edx /* edx has ebp */ + + movl function_trace_op, %ecx + subl $MCOUNT_INSN_SIZE, %eax + +.globl ftrace_call +ftrace_call: + call ftrace_stub + + addl $4, %esp /* skip NULL pointer */ + popl %edx + popl %ecx + popl %eax +#ifdef USING_FRAME_POINTER + popl %ebp +# ifdef CC_USING_FENTRY + addl $4,%esp /* skip function ip */ + popl %ebp /* this is the orig bp */ + addl $4, %esp /* skip parent ip */ +# endif +#endif +.Lftrace_ret: +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +.globl ftrace_graph_call +ftrace_graph_call: + jmp ftrace_stub +#endif + +/* This is weak to keep gas from relaxing the jumps */ +WEAK(ftrace_stub) + ret +END(ftrace_caller) + +ENTRY(ftrace_regs_caller) + /* + * i386 does not save SS and ESP when coming from kernel. + * Instead, to get sp, ®s->sp is used (see ptrace.h). + * Unfortunately, that means eflags must be at the same location + * as the current return ip is. We move the return ip into the + * regs->ip location, and move flags into the return ip location. + */ + pushl $__KERNEL_CS + pushl 4(%esp) /* Save the return ip */ + pushl $0 /* Load 0 into orig_ax */ + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl %eax + + /* Get flags and place them into the return ip slot */ + pushf + popl %eax + movl %eax, 8*4(%esp) + + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + + movl 12*4(%esp), %eax /* Load ip (1st parameter) */ + subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ +#ifdef CC_USING_FENTRY + movl 15*4(%esp), %edx /* Load parent ip (2nd parameter) */ +#else + movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ +#endif + movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ + pushl %esp /* Save pt_regs as 4th parameter */ + +GLOBAL(ftrace_regs_call) + call ftrace_stub + + addl $4, %esp /* Skip pt_regs */ + + /* restore flags */ + push 14*4(%esp) + popf + + /* Move return ip back to its original location */ + movl 12*4(%esp), %eax + movl %eax, 14*4(%esp) + + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebp + popl %eax + popl %ds + popl %es + popl %fs + popl %gs + + /* use lea to not affect flags */ + lea 3*4(%esp), %esp /* Skip orig_ax, ip and cs */ + + jmp .Lftrace_ret +#else /* ! CONFIG_DYNAMIC_FTRACE */ + +ENTRY(function_hook) + cmpl $__PAGE_OFFSET, %esp + jb ftrace_stub /* Paging not enabled yet? */ + + cmpl $ftrace_stub, ftrace_trace_function + jnz .Ltrace +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + cmpl $ftrace_stub, ftrace_graph_return + jnz ftrace_graph_caller + + cmpl $ftrace_graph_entry_stub, ftrace_graph_entry + jnz ftrace_graph_caller +#endif +.globl ftrace_stub +ftrace_stub: + ret + + /* taken from glibc */ +.Ltrace: + pushl %eax + pushl %ecx + pushl %edx + movl 0xc(%esp), %eax + movl 0x4(%ebp), %edx + subl $MCOUNT_INSN_SIZE, %eax + + call *ftrace_trace_function + + popl %edx + popl %ecx + popl %eax + jmp ftrace_stub +END(function_hook) +#endif /* CONFIG_DYNAMIC_FTRACE */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(ftrace_graph_caller) + pushl %eax + pushl %ecx + pushl %edx + movl 3*4(%esp), %eax + /* Even with frame pointers, fentry doesn't have one here */ +#ifdef CC_USING_FENTRY + lea 4*4(%esp), %edx + movl $0, %ecx +#else + lea 0x4(%ebp), %edx + movl (%ebp), %ecx +#endif + subl $MCOUNT_INSN_SIZE, %eax + call prepare_ftrace_return + popl %edx + popl %ecx + popl %eax + ret +END(ftrace_graph_caller) + +.globl return_to_handler +return_to_handler: + pushl %eax + pushl %edx +#ifdef CC_USING_FENTRY + movl $0, %eax +#else + movl %ebp, %eax +#endif + call ftrace_return_to_handler + movl %eax, %ecx + popl %edx + popl %eax + jmp *%ecx +#endif diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/ftrace_64.S index 7b0d3da52fb4..1dfac634bbf7 100644 --- a/arch/x86/kernel/mcount_64.S +++ b/arch/x86/kernel/ftrace_64.S @@ -1,6 +1,4 @@ /* - * linux/arch/x86_64/mcount_64.S - * * Copyright (C) 2014 Steven Rostedt, Red Hat Inc */ @@ -13,9 +11,6 @@ .code64 .section .entry.text, "ax" - -#ifdef CONFIG_FUNCTION_TRACER - #ifdef CC_USING_FENTRY # define function_hook __fentry__ EXPORT_SYMBOL(__fentry__) @@ -297,7 +292,6 @@ trace: jmp fgraph_trace END(function_hook) #endif /* CONFIG_DYNAMIC_FTRACE */ -#endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER ENTRY(ftrace_graph_caller) diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index e5fb436a6548..538ec012b371 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -12,7 +12,7 @@ #include <asm/setup.h> #include <asm/sections.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/page.h> #include <asm/apic.h> #include <asm/io_apic.h> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 54a2372f5dbb..43b7002f44fb 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -4,6 +4,7 @@ * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE */ +#define DISABLE_BRANCH_PROFILING #include <linux/init.h> #include <linux/linkage.h> #include <linux/types.h> @@ -23,7 +24,7 @@ #include <asm/tlbflush.h> #include <asm/sections.h> #include <asm/kdebug.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/bios_ebda.h> #include <asm/bootparam_utils.h> #include <asm/microcode.h> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index b467b14b03eb..ac9d327d2e42 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -269,10 +269,8 @@ ENTRY(secondary_startup_64) /* rsi is pointer to real mode structure with interesting info. pass it to C */ movq %rsi, %rdi - jmp start_cpu -ENDPROC(secondary_startup_64) -ENTRY(start_cpu) +.Ljump_to_C_code: /* * Jump to run C code and to be on a real kernel address. * Since we are running on identity-mapped space we have to jump @@ -305,7 +303,7 @@ ENTRY(start_cpu) pushq %rax # target address in negative space lretq .Lafter_lret: -ENDPROC(start_cpu) +ENDPROC(secondary_startup_64) #include "verify_cpu.S" @@ -313,11 +311,11 @@ ENDPROC(start_cpu) /* * Boot CPU0 entry point. It's called from play_dead(). Everything has been set * up already except stack. We just set up stack here. Then call - * start_secondary() via start_cpu(). + * start_secondary() via .Ljump_to_C_code. */ ENTRY(start_cpu0) movq initial_stack(%rip), %rsp - jmp start_cpu + jmp .Ljump_to_C_code ENDPROC(start_cpu0) #endif diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index dc6ba5bda9fc..89ff7af2de50 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -354,7 +354,7 @@ static int hpet_resume(struct clock_event_device *evt, int timer) irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq)); irq_domain_activate_irq(irq_get_irq_data(hdev->irq)); - disable_irq(hdev->irq); + disable_hardirq(hdev->irq); irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu)); enable_irq(hdev->irq); } diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 4d8183b5f113..f34fe7444836 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -394,6 +394,9 @@ int check_irq_vectors_for_cpu_disable(void) !cpumask_subset(&affinity_new, &online_new)) this_count++; } + /* No need to check any further. */ + if (!this_count) + return 0; count = 0; for_each_online_cpu(cpu) { @@ -411,8 +414,10 @@ int check_irq_vectors_for_cpu_disable(void) for (vector = FIRST_EXTERNAL_VECTOR; vector < first_system_vector; vector++) { if (!test_bit(vector, used_vectors) && - IS_ERR_OR_NULL(per_cpu(vector_irq, cpu)[vector])) - count++; + IS_ERR_OR_NULL(per_cpu(vector_irq, cpu)[vector])) { + if (++count == this_count) + return 0; + } } } diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 1423ab1b0312..7468c6987547 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -195,7 +195,5 @@ void __init native_init_IRQ(void) if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) setup_irq(2, &irq2); -#ifdef CONFIG_X86_32 irq_ctx_init(smp_processor_id()); -#endif } diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c index bdb83e431d89..38b64587b31b 100644 --- a/arch/x86/kernel/kdebugfs.c +++ b/arch/x86/kernel/kdebugfs.c @@ -167,7 +167,7 @@ static int __init boot_params_kdebugfs_init(void) struct dentry *dbp, *version, *data; int error = -ENOMEM; - dbp = debugfs_create_dir("boot_params", NULL); + dbp = debugfs_create_dir("boot_params", arch_debugfs_dir); if (!dbp) return -ENOMEM; diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index d0a814a9d96a..9d7fd5e6689a 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -25,6 +25,7 @@ #include <asm/setup.h> #include <asm/crash.h> #include <asm/efi.h> +#include <asm/e820/api.h> #include <asm/kexec-bzimage64.h> #define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */ @@ -99,15 +100,14 @@ static int setup_e820_entries(struct boot_params *params) { unsigned int nr_e820_entries; - nr_e820_entries = e820_saved->nr_map; + nr_e820_entries = e820_table_firmware->nr_entries; - /* TODO: Pass entries more than E820MAX in bootparams setup data */ - if (nr_e820_entries > E820MAX) - nr_e820_entries = E820MAX; + /* TODO: Pass entries more than E820_MAX_ENTRIES_ZEROPAGE in bootparams setup data */ + if (nr_e820_entries > E820_MAX_ENTRIES_ZEROPAGE) + nr_e820_entries = E820_MAX_ENTRIES_ZEROPAGE; params->e820_entries = nr_e820_entries; - memcpy(¶ms->e820_map, &e820_saved->map, - nr_e820_entries * sizeof(struct e820entry)); + memcpy(¶ms->e820_table, &e820_table_firmware->entries, nr_e820_entries*sizeof(struct e820_entry)); return 0; } @@ -232,10 +232,10 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, nr_e820_entries = params->e820_entries; for (i = 0; i < nr_e820_entries; i++) { - if (params->e820_map[i].type != E820_RAM) + if (params->e820_table[i].type != E820_TYPE_RAM) continue; - start = params->e820_map[i].addr; - end = params->e820_map[i].addr + params->e820_map[i].size - 1; + start = params->e820_table[i].addr; + end = params->e820_table[i].addr + params->e820_table[i].size - 1; if ((start <= 0x100000) && end > 0x100000) { mem_k = (end >> 10) - (0x100000 >> 10); diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h index c6ee63f927ab..db2182d63ed0 100644 --- a/arch/x86/kernel/kprobes/common.h +++ b/arch/x86/kernel/kprobes/common.h @@ -67,7 +67,7 @@ #endif /* Ensure if the instruction can be boostable */ -extern int can_boost(kprobe_opcode_t *instruction); +extern int can_boost(struct insn *insn, void *orig_addr); /* Recover instruction if given address is probed */ extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr); @@ -75,7 +75,7 @@ extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf, * Copy an instruction and adjust the displacement if the instruction * uses the %rip-relative addressing mode. */ -extern int __copy_instruction(u8 *dest, u8 *src); +extern int __copy_instruction(u8 *dest, u8 *src, struct insn *insn); /* Generate a relative-jump/call instruction */ extern void synthesize_reljump(void *from, void *to); diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 6384eb754a58..19e1f2a6d7b0 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -164,42 +164,38 @@ static kprobe_opcode_t *skip_prefixes(kprobe_opcode_t *insn) NOKPROBE_SYMBOL(skip_prefixes); /* - * Returns non-zero if opcode is boostable. + * Returns non-zero if INSN is boostable. * RIP relative instructions are adjusted at copying time in 64 bits mode */ -int can_boost(kprobe_opcode_t *opcodes) +int can_boost(struct insn *insn, void *addr) { kprobe_opcode_t opcode; - kprobe_opcode_t *orig_opcodes = opcodes; - if (search_exception_tables((unsigned long)opcodes)) + if (search_exception_tables((unsigned long)addr)) return 0; /* Page fault may occur on this address. */ -retry: - if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1) - return 0; - opcode = *(opcodes++); - /* 2nd-byte opcode */ - if (opcode == 0x0f) { - if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1) - return 0; - return test_bit(*opcodes, + if (insn->opcode.nbytes == 2) + return test_bit(insn->opcode.bytes[1], (unsigned long *)twobyte_is_boostable); - } + + if (insn->opcode.nbytes != 1) + return 0; + + /* Can't boost Address-size override prefix */ + if (unlikely(inat_is_address_size_prefix(insn->attr))) + return 0; + + opcode = insn->opcode.bytes[0]; switch (opcode & 0xf0) { -#ifdef CONFIG_X86_64 - case 0x40: - goto retry; /* REX prefix is boostable */ -#endif case 0x60: - if (0x63 < opcode && opcode < 0x67) - goto retry; /* prefixes */ - /* can't boost Address-size override and bound */ - return (opcode != 0x62 && opcode != 0x67); + /* can't boost "bound" */ + return (opcode != 0x62); case 0x70: return 0; /* can't boost conditional jump */ + case 0x90: + return opcode != 0x9a; /* can't boost call far */ case 0xc0: /* can't boost software-interruptions */ return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf; @@ -210,14 +206,9 @@ retry: /* can boost in/out and absolute jmps */ return ((opcode & 0x04) || opcode == 0xea); case 0xf0: - if ((opcode & 0x0c) == 0 && opcode != 0xf1) - goto retry; /* lock/rep(ne) prefix */ /* clear and set flags are boostable */ return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe)); default: - /* segment override prefixes are boostable */ - if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e) - goto retry; /* prefixes */ /* CS override prefix and call are not boostable */ return (opcode != 0x2e && opcode != 0x9a); } @@ -264,7 +255,10 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) * Fortunately, we know that the original code is the ideal 5-byte * long NOP. */ - memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + if (probe_kernel_read(buf, (void *)addr, + MAX_INSN_SIZE * sizeof(kprobe_opcode_t))) + return 0UL; + if (faddr) memcpy(buf, ideal_nops[NOP_ATOMIC5], 5); else @@ -276,7 +270,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) * Recover the probed instruction at addr for further analysis. * Caller must lock kprobes by kprobe_mutex, or disable preemption * for preventing to release referencing kprobes. - * Returns zero if the instruction can not get recovered. + * Returns zero if the instruction can not get recovered (or access failed). */ unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) { @@ -348,37 +342,36 @@ static int is_IF_modifier(kprobe_opcode_t *insn) } /* - * Copy an instruction and adjust the displacement if the instruction - * uses the %rip-relative addressing mode. - * If it does, Return the address of the 32-bit displacement word. - * If not, return null. - * Only applicable to 64-bit x86. + * Copy an instruction with recovering modified instruction by kprobes + * and adjust the displacement if the instruction uses the %rip-relative + * addressing mode. + * This returns the length of copied instruction, or 0 if it has an error. */ -int __copy_instruction(u8 *dest, u8 *src) +int __copy_instruction(u8 *dest, u8 *src, struct insn *insn) { - struct insn insn; kprobe_opcode_t buf[MAX_INSN_SIZE]; - int length; unsigned long recovered_insn = recover_probed_instruction(buf, (unsigned long)src); - if (!recovered_insn) + if (!recovered_insn || !insn) + return 0; + + /* This can access kernel text if given address is not recovered */ + if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE)) return 0; - kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); - insn_get_length(&insn); - length = insn.length; + + kernel_insn_init(insn, dest, MAX_INSN_SIZE); + insn_get_length(insn); /* Another subsystem puts a breakpoint, failed to recover */ - if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) + if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION) return 0; - memcpy(dest, insn.kaddr, length); #ifdef CONFIG_X86_64 - if (insn_rip_relative(&insn)) { + /* Only x86_64 has RIP relative instructions */ + if (insn_rip_relative(insn)) { s64 newdisp; u8 *disp; - kernel_insn_init(&insn, dest, length); - insn_get_displacement(&insn); /* * The copied instruction uses the %rip-relative addressing * mode. Adjust the displacement for the difference between @@ -391,36 +384,57 @@ int __copy_instruction(u8 *dest, u8 *src) * extension of the original signed 32-bit displacement would * have given. */ - newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest; + newdisp = (u8 *) src + (s64) insn->displacement.value + - (u8 *) dest; if ((s64) (s32) newdisp != newdisp) { pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp); - pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", src, dest, insn.displacement.value); + pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", + src, dest, insn->displacement.value); return 0; } - disp = (u8 *) dest + insn_offset_displacement(&insn); + disp = (u8 *) dest + insn_offset_displacement(insn); *(s32 *) disp = (s32) newdisp; } #endif - return length; + return insn->length; +} + +/* Prepare reljump right after instruction to boost */ +static void prepare_boost(struct kprobe *p, struct insn *insn) +{ + if (can_boost(insn, p->addr) && + MAX_INSN_SIZE - insn->length >= RELATIVEJUMP_SIZE) { + /* + * These instructions can be executed directly if it + * jumps back to correct address. + */ + synthesize_reljump(p->ainsn.insn + insn->length, + p->addr + insn->length); + p->ainsn.boostable = true; + } else { + p->ainsn.boostable = false; + } } static int arch_copy_kprobe(struct kprobe *p) { - int ret; + struct insn insn; + int len; + + set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1); /* Copy an instruction with recovering if other optprobe modifies it.*/ - ret = __copy_instruction(p->ainsn.insn, p->addr); - if (!ret) + len = __copy_instruction(p->ainsn.insn, p->addr, &insn); + if (!len) return -EINVAL; /* * __copy_instruction can modify the displacement of the instruction, * but it doesn't affect boostable check. */ - if (can_boost(p->ainsn.insn)) - p->ainsn.boostable = 0; - else - p->ainsn.boostable = -1; + prepare_boost(p, &insn); + + set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1); /* Check whether the instruction modifies Interrupt Flag or not */ p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn); @@ -459,7 +473,7 @@ void arch_disarm_kprobe(struct kprobe *p) void arch_remove_kprobe(struct kprobe *p) { if (p->ainsn.insn) { - free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1)); + free_insn_slot(p->ainsn.insn, p->ainsn.boostable); p->ainsn.insn = NULL; } } @@ -531,7 +545,7 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs, return; #if !defined(CONFIG_PREEMPT) - if (p->ainsn.boostable == 1 && !p->post_handler) { + if (p->ainsn.boostable && !p->post_handler) { /* Boost up -- we can execute copied instructions directly */ if (!reenter) reset_current_kprobe(); @@ -851,7 +865,7 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs, case 0xcf: case 0xea: /* jmp absolute -- ip is correct */ /* ip is already adjusted, no more changes required */ - p->ainsn.boostable = 1; + p->ainsn.boostable = true; goto no_change; case 0xe8: /* call relative - Fix return addr */ *tos = orig_ip + (*tos - copy_ip); @@ -876,28 +890,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs, * jmp near and far, absolute indirect * ip is correct. And this is boostable */ - p->ainsn.boostable = 1; + p->ainsn.boostable = true; goto no_change; } default: break; } - if (p->ainsn.boostable == 0) { - if ((regs->ip > copy_ip) && - (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) { - /* - * These instructions can be executed directly if it - * jumps back to correct address. - */ - synthesize_reljump((void *)regs->ip, - (void *)orig_ip + (regs->ip - copy_ip)); - p->ainsn.boostable = 1; - } else { - p->ainsn.boostable = -1; - } - } - regs->ip += orig_ip - copy_ip; no_change: diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c index 5f8f0b3cc674..041f7b6dfa0f 100644 --- a/arch/x86/kernel/kprobes/ftrace.c +++ b/arch/x86/kernel/kprobes/ftrace.c @@ -94,6 +94,6 @@ NOKPROBE_SYMBOL(kprobe_ftrace_handler); int arch_prepare_kprobe_ftrace(struct kprobe *p) { p->ainsn.insn = NULL; - p->ainsn.boostable = -1; + p->ainsn.boostable = false; return 0; } diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 3d1bee9d6a72..9aadff3d0902 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -65,7 +65,10 @@ found: * overwritten by jump destination address. In this case, original * bytes must be recovered from op->optinsn.copied_insn buffer. */ - memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + if (probe_kernel_read(buf, (void *)addr, + MAX_INSN_SIZE * sizeof(kprobe_opcode_t))) + return 0UL; + if (addr == (unsigned long)kp->addr) { buf[0] = kp->opcode; memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE); @@ -174,11 +177,12 @@ NOKPROBE_SYMBOL(optimized_callback); static int copy_optimized_instructions(u8 *dest, u8 *src) { + struct insn insn; int len = 0, ret; while (len < RELATIVEJUMP_SIZE) { - ret = __copy_instruction(dest + len, src + len); - if (!ret || !can_boost(dest + len)) + ret = __copy_instruction(dest + len, src + len, &insn); + if (!ret || !can_boost(&insn, src + len)) return -EINVAL; len += ret; } @@ -350,6 +354,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, } buf = (u8 *)op->optinsn.insn; + set_memory_rw((unsigned long)buf & PAGE_MASK, 1); /* Copy instructions into the out-of-line buffer */ ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr); @@ -372,6 +377,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size, (u8 *)op->kp.addr + op->optinsn.size); + set_memory_ro((unsigned long)buf & PAGE_MASK, 1); + flush_icache_range((unsigned long) buf, (unsigned long) buf + TMPL_END_IDX + op->optinsn.size + RELATIVEJUMP_SIZE); diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 469b23d6acc2..5f43cec296c5 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c @@ -103,6 +103,7 @@ static void machine_kexec_page_table_set_one( pgd_t *pgd, pmd_t *pmd, pte_t *pte, unsigned long vaddr, unsigned long paddr) { + p4d_t *p4d; pud_t *pud; pgd += pgd_index(vaddr); @@ -110,7 +111,8 @@ static void machine_kexec_page_table_set_one( if (!(pgd_val(*pgd) & _PAGE_PRESENT)) set_pgd(pgd, __pgd(__pa(pmd) | _PAGE_PRESENT)); #endif - pud = pud_offset(pgd, vaddr); + p4d = p4d_offset(pgd, vaddr); + pud = pud_offset(p4d, vaddr); pmd = pmd_offset(pud, vaddr); if (!(pmd_val(*pmd) & _PAGE_PRESENT)) set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE)); diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 307b1f4543de..085c3b300d32 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -36,6 +36,7 @@ static struct kexec_file_ops *kexec_file_loaders[] = { static void free_transition_pgtable(struct kimage *image) { + free_page((unsigned long)image->arch.p4d); free_page((unsigned long)image->arch.pud); free_page((unsigned long)image->arch.pmd); free_page((unsigned long)image->arch.pte); @@ -43,6 +44,7 @@ static void free_transition_pgtable(struct kimage *image) static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) { + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -53,13 +55,21 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE); pgd += pgd_index(vaddr); if (!pgd_present(*pgd)) { + p4d = (p4d_t *)get_zeroed_page(GFP_KERNEL); + if (!p4d) + goto err; + image->arch.p4d = p4d; + set_pgd(pgd, __pgd(__pa(p4d) | _KERNPG_TABLE)); + } + p4d = p4d_offset(pgd, vaddr); + if (!p4d_present(*p4d)) { pud = (pud_t *)get_zeroed_page(GFP_KERNEL); if (!pud) goto err; image->arch.pud = pud; - set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE)); + set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE)); } - pud = pud_offset(pgd, vaddr); + pud = pud_offset(p4d, vaddr); if (!pud_present(*pud)) { pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL); if (!pmd) @@ -194,19 +204,22 @@ static int arch_update_purgatory(struct kimage *image) /* Setup copying of backup region */ if (image->type == KEXEC_TYPE_CRASH) { - ret = kexec_purgatory_get_set_symbol(image, "backup_dest", + ret = kexec_purgatory_get_set_symbol(image, + "purgatory_backup_dest", &image->arch.backup_load_addr, sizeof(image->arch.backup_load_addr), 0); if (ret) return ret; - ret = kexec_purgatory_get_set_symbol(image, "backup_src", + ret = kexec_purgatory_get_set_symbol(image, + "purgatory_backup_src", &image->arch.backup_src_start, sizeof(image->arch.backup_src_start), 0); if (ret) return ret; - ret = kexec_purgatory_get_set_symbol(image, "backup_sz", + ret = kexec_purgatory_get_set_symbol(image, + "purgatory_backup_sz", &image->arch.backup_src_sz, sizeof(image->arch.backup_src_sz), 0); if (ret) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 0f8d20497383..0d904d759ff1 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -26,7 +26,7 @@ #include <asm/io_apic.h> #include <asm/proto.h> #include <asm/bios_ebda.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/setup.h> #include <asm/smp.h> @@ -826,10 +826,10 @@ static int __init parse_alloc_mptable_opt(char *p) } early_param("alloc_mptable", parse_alloc_mptable_opt); -void __init early_reserve_e820_mpc_new(void) +void __init e820__memblock_alloc_reserved_mpc_new(void) { if (enable_update_mptable && alloc_mptable) - mpc_new_phys = early_reserve_e820(mpc_new_length, 4); + mpc_new_phys = e820__memblock_alloc_reserved(mpc_new_length, 4); } static int __init update_mp_table(void) diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index f088ea4c66e7..446c8aa09b9b 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -166,11 +166,9 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action) spin_lock_irqsave(&desc->lock, flags); /* - * most handlers of type NMI_UNKNOWN never return because - * they just assume the NMI is theirs. Just a sanity check - * to manage expectations + * Indicate if there are multiple registrations on the + * internal NMI handler call chains (SERR and IO_CHECK). */ - WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head)); WARN_ON_ONCE(type == NMI_SERR && !list_empty(&desc->head)); WARN_ON_ONCE(type == NMI_IO_CHECK && !list_empty(&desc->head)); @@ -224,17 +222,6 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs) pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n", reason, smp_processor_id()); - /* - * On some machines, PCI SERR line is used to report memory - * errors. EDAC makes use of it. - */ -#if defined(CONFIG_EDAC) - if (edac_handler_set()) { - edac_atomic_assert_error(); - return; - } -#endif - if (panic_on_unrecovered_nmi) nmi_panic(regs, "NMI: Not continuing"); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 4797e87b0fb6..3586996fc50d 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -405,9 +405,11 @@ struct pv_mmu_ops pv_mmu_ops __ro_after_init = { .alloc_pte = paravirt_nop, .alloc_pmd = paravirt_nop, .alloc_pud = paravirt_nop, + .alloc_p4d = paravirt_nop, .release_pte = paravirt_nop, .release_pmd = paravirt_nop, .release_pud = paravirt_nop, + .release_p4d = paravirt_nop, .set_pte = native_set_pte, .set_pte_at = native_set_pte_at, @@ -430,12 +432,19 @@ struct pv_mmu_ops pv_mmu_ops __ro_after_init = { .pmd_val = PTE_IDENT, .make_pmd = PTE_IDENT, -#if CONFIG_PGTABLE_LEVELS == 4 +#if CONFIG_PGTABLE_LEVELS >= 4 .pud_val = PTE_IDENT, .make_pud = PTE_IDENT, + .set_p4d = native_set_p4d, + +#if CONFIG_PGTABLE_LEVELS >= 5 + .p4d_val = PTE_IDENT, + .make_p4d = PTE_IDENT, + .set_pgd = native_set_pgd, -#endif +#endif /* CONFIG_PGTABLE_LEVELS >= 5 */ +#endif /* CONFIG_PGTABLE_LEVELS >= 4 */ #endif /* CONFIG_PGTABLE_LEVELS >= 3 */ .pte_val = PTE_IDENT, diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 0c150c06fa5a..fda7867046d0 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -1007,9 +1007,8 @@ static void __init calgary_enable_translation(struct pci_dev *dev) writel(cpu_to_be32(val32), target); readl(target); /* flush */ - init_timer(&tbl->watchdog_timer); - tbl->watchdog_timer.function = &calgary_watchdog; - tbl->watchdog_timer.data = (unsigned long)dev; + setup_timer(&tbl->watchdog_timer, &calgary_watchdog, + (unsigned long)dev); mod_timer(&tbl->watchdog_timer, jiffies); } diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c index d5f15c3f7b25..963e3fb56437 100644 --- a/arch/x86/kernel/probe_roms.c +++ b/arch/x86/kernel/probe_roms.c @@ -14,7 +14,7 @@ #include <asm/probe_roms.h> #include <asm/pci-direct.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mmzone.h> #include <asm/setup.h> #include <asm/sections.h> diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index f67591561711..0bb88428cbf2 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -37,6 +37,7 @@ #include <asm/vm86.h> #include <asm/switch_to.h> #include <asm/desc.h> +#include <asm/prctl.h> /* * per-CPU TSS segments. Threads are completely 'soft' on Linux, @@ -124,11 +125,6 @@ void flush_thread(void) fpu__clear(&tsk->thread.fpu); } -static void hard_disable_TSC(void) -{ - cr4_set_bits(X86_CR4_TSD); -} - void disable_TSC(void) { preempt_disable(); @@ -137,15 +133,10 @@ void disable_TSC(void) * Must flip the CPU state synchronously with * TIF_NOTSC in the current running context. */ - hard_disable_TSC(); + cr4_set_bits(X86_CR4_TSD); preempt_enable(); } -static void hard_enable_TSC(void) -{ - cr4_clear_bits(X86_CR4_TSD); -} - static void enable_TSC(void) { preempt_disable(); @@ -154,7 +145,7 @@ static void enable_TSC(void) * Must flip the CPU state synchronously with * TIF_NOTSC in the current running context. */ - hard_enable_TSC(); + cr4_clear_bits(X86_CR4_TSD); preempt_enable(); } @@ -182,54 +173,129 @@ int set_tsc_mode(unsigned int val) return 0; } -void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, - struct tss_struct *tss) -{ - struct thread_struct *prev, *next; - - prev = &prev_p->thread; - next = &next_p->thread; +DEFINE_PER_CPU(u64, msr_misc_features_shadow); - if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^ - test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) { - unsigned long debugctl = get_debugctlmsr(); +static void set_cpuid_faulting(bool on) +{ + u64 msrval; - debugctl &= ~DEBUGCTLMSR_BTF; - if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) - debugctl |= DEBUGCTLMSR_BTF; + msrval = this_cpu_read(msr_misc_features_shadow); + msrval &= ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT; + msrval |= (on << MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT); + this_cpu_write(msr_misc_features_shadow, msrval); + wrmsrl(MSR_MISC_FEATURES_ENABLES, msrval); +} - update_debugctlmsr(debugctl); +static void disable_cpuid(void) +{ + preempt_disable(); + if (!test_and_set_thread_flag(TIF_NOCPUID)) { + /* + * Must flip the CPU state synchronously with + * TIF_NOCPUID in the current running context. + */ + set_cpuid_faulting(true); } + preempt_enable(); +} - if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ - test_tsk_thread_flag(next_p, TIF_NOTSC)) { - /* prev and next are different */ - if (test_tsk_thread_flag(next_p, TIF_NOTSC)) - hard_disable_TSC(); - else - hard_enable_TSC(); +static void enable_cpuid(void) +{ + preempt_disable(); + if (test_and_clear_thread_flag(TIF_NOCPUID)) { + /* + * Must flip the CPU state synchronously with + * TIF_NOCPUID in the current running context. + */ + set_cpuid_faulting(false); } + preempt_enable(); +} + +static int get_cpuid_mode(void) +{ + return !test_thread_flag(TIF_NOCPUID); +} + +static int set_cpuid_mode(struct task_struct *task, unsigned long cpuid_enabled) +{ + if (!static_cpu_has(X86_FEATURE_CPUID_FAULT)) + return -ENODEV; + + if (cpuid_enabled) + enable_cpuid(); + else + disable_cpuid(); + + return 0; +} + +/* + * Called immediately after a successful exec. + */ +void arch_setup_new_exec(void) +{ + /* If cpuid was previously disabled for this task, re-enable it. */ + if (test_thread_flag(TIF_NOCPUID)) + enable_cpuid(); +} - if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { +static inline void switch_to_bitmap(struct tss_struct *tss, + struct thread_struct *prev, + struct thread_struct *next, + unsigned long tifp, unsigned long tifn) +{ + if (tifn & _TIF_IO_BITMAP) { /* * Copy the relevant range of the IO bitmap. * Normally this is 128 bytes or less: */ memcpy(tss->io_bitmap, next->io_bitmap_ptr, max(prev->io_bitmap_max, next->io_bitmap_max)); - /* * Make sure that the TSS limit is correct for the CPU * to notice the IO bitmap. */ refresh_tss_limit(); - } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { + } else if (tifp & _TIF_IO_BITMAP) { /* * Clear any possible leftover bits: */ memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); } +} + +void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, + struct tss_struct *tss) +{ + struct thread_struct *prev, *next; + unsigned long tifp, tifn; + + prev = &prev_p->thread; + next = &next_p->thread; + + tifn = READ_ONCE(task_thread_info(next_p)->flags); + tifp = READ_ONCE(task_thread_info(prev_p)->flags); + switch_to_bitmap(tss, prev, next, tifp, tifn); + propagate_user_return_notify(prev_p, next_p); + + if ((tifp & _TIF_BLOCKSTEP || tifn & _TIF_BLOCKSTEP) && + arch_has_block_step()) { + unsigned long debugctl, msk; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + debugctl &= ~DEBUGCTLMSR_BTF; + msk = tifn & _TIF_BLOCKSTEP; + debugctl |= (msk >> TIF_BLOCKSTEP) << DEBUGCTLMSR_BTF_SHIFT; + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + } + + if ((tifp ^ tifn) & _TIF_NOTSC) + cr4_toggle_bits(X86_CR4_TSD); + + if ((tifp ^ tifn) & _TIF_NOCPUID) + set_cpuid_faulting(!!(tifn & _TIF_NOCPUID)); } /* @@ -550,3 +616,16 @@ out: put_task_stack(p); return ret; } + +long do_arch_prctl_common(struct task_struct *task, int option, + unsigned long cpuid_enabled) +{ + switch (option) { + case ARCH_GET_CPUID: + return get_cpuid_mode(); + case ARCH_SET_CPUID: + return set_cpuid_mode(task, cpuid_enabled); + } + + return -EINVAL; +} diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 4c818f8bc135..ff40e74c9181 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -37,6 +37,7 @@ #include <linux/uaccess.h> #include <linux/io.h> #include <linux/kdebug.h> +#include <linux/syscalls.h> #include <asm/pgtable.h> #include <asm/ldt.h> @@ -56,6 +57,7 @@ #include <asm/switch_to.h> #include <asm/vm86.h> #include <asm/intel_rdt.h> +#include <asm/proto.h> void __show_regs(struct pt_regs *regs, int all) { @@ -304,3 +306,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) return prev_p; } + +SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) +{ + return do_arch_prctl_common(current, option, arg2); +} diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index d6b784a5520d..825a1e47cf3e 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -37,6 +37,7 @@ #include <linux/uaccess.h> #include <linux/io.h> #include <linux/ftrace.h> +#include <linux/syscalls.h> #include <asm/pgtable.h> #include <asm/processor.h> @@ -52,6 +53,11 @@ #include <asm/xen/hypervisor.h> #include <asm/vdso.h> #include <asm/intel_rdt.h> +#include <asm/unistd.h> +#ifdef CONFIG_IA32_EMULATION +/* Not included via unistd.h */ +#include <asm/unistd_32_ia32.h> +#endif __visible DEFINE_PER_CPU(unsigned long, rsp_scratch); @@ -204,7 +210,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp, (struct user_desc __user *)tls, 0); else #endif - err = do_arch_prctl(p, ARCH_SET_FS, tls); + err = do_arch_prctl_64(p, ARCH_SET_FS, tls); if (err) goto out; } @@ -493,6 +499,8 @@ void set_personality_64bit(void) clear_thread_flag(TIF_IA32); clear_thread_flag(TIF_ADDR32); clear_thread_flag(TIF_X32); + /* Pretend that this comes from a 64bit execve */ + task_pt_regs(current)->orig_ax = __NR_execve; /* Ensure the corresponding mm is not marked. */ if (current->mm) @@ -505,32 +513,50 @@ void set_personality_64bit(void) current->personality &= ~READ_IMPLIES_EXEC; } -void set_personality_ia32(bool x32) +static void __set_personality_x32(void) { - /* inherit personality from parent */ +#ifdef CONFIG_X86_X32 + clear_thread_flag(TIF_IA32); + set_thread_flag(TIF_X32); + if (current->mm) + current->mm->context.ia32_compat = TIF_X32; + current->personality &= ~READ_IMPLIES_EXEC; + /* + * in_compat_syscall() uses the presence of the x32 syscall bit + * flag to determine compat status. The x86 mmap() code relies on + * the syscall bitness so set x32 syscall bit right here to make + * in_compat_syscall() work during exec(). + * + * Pretend to come from a x32 execve. + */ + task_pt_regs(current)->orig_ax = __NR_x32_execve | __X32_SYSCALL_BIT; + current->thread.status &= ~TS_COMPAT; +#endif +} + +static void __set_personality_ia32(void) +{ +#ifdef CONFIG_IA32_EMULATION + set_thread_flag(TIF_IA32); + clear_thread_flag(TIF_X32); + if (current->mm) + current->mm->context.ia32_compat = TIF_IA32; + current->personality |= force_personality32; + /* Prepare the first "return" to user space */ + task_pt_regs(current)->orig_ax = __NR_ia32_execve; + current->thread.status |= TS_COMPAT; +#endif +} +void set_personality_ia32(bool x32) +{ /* Make sure to be in 32bit mode */ set_thread_flag(TIF_ADDR32); - /* Mark the associated mm as containing 32-bit tasks. */ - if (x32) { - clear_thread_flag(TIF_IA32); - set_thread_flag(TIF_X32); - if (current->mm) - current->mm->context.ia32_compat = TIF_X32; - current->personality &= ~READ_IMPLIES_EXEC; - /* in_compat_syscall() uses the presence of the x32 - syscall bit flag to determine compat status */ - current->thread.status &= ~TS_COMPAT; - } else { - set_thread_flag(TIF_IA32); - clear_thread_flag(TIF_X32); - if (current->mm) - current->mm->context.ia32_compat = TIF_IA32; - current->personality |= force_personality32; - /* Prepare the first "return" to user space */ - current->thread.status |= TS_COMPAT; - } + if (x32) + __set_personality_x32(); + else + __set_personality_ia32(); } EXPORT_SYMBOL_GPL(set_personality_ia32); @@ -547,70 +573,72 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr) } #endif -long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) +long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) { int ret = 0; int doit = task == current; int cpu; - switch (code) { + switch (option) { case ARCH_SET_GS: - if (addr >= TASK_SIZE_MAX) + if (arg2 >= TASK_SIZE_MAX) return -EPERM; cpu = get_cpu(); task->thread.gsindex = 0; - task->thread.gsbase = addr; + task->thread.gsbase = arg2; if (doit) { load_gs_index(0); - ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr); + ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, arg2); } put_cpu(); break; case ARCH_SET_FS: /* Not strictly needed for fs, but do it for symmetry with gs */ - if (addr >= TASK_SIZE_MAX) + if (arg2 >= TASK_SIZE_MAX) return -EPERM; cpu = get_cpu(); task->thread.fsindex = 0; - task->thread.fsbase = addr; + task->thread.fsbase = arg2; if (doit) { /* set the selector to 0 to not confuse __switch_to */ loadsegment(fs, 0); - ret = wrmsrl_safe(MSR_FS_BASE, addr); + ret = wrmsrl_safe(MSR_FS_BASE, arg2); } put_cpu(); break; case ARCH_GET_FS: { unsigned long base; + if (doit) rdmsrl(MSR_FS_BASE, base); else base = task->thread.fsbase; - ret = put_user(base, (unsigned long __user *)addr); + ret = put_user(base, (unsigned long __user *)arg2); break; } case ARCH_GET_GS: { unsigned long base; + if (doit) rdmsrl(MSR_KERNEL_GS_BASE, base); else base = task->thread.gsbase; - ret = put_user(base, (unsigned long __user *)addr); + ret = put_user(base, (unsigned long __user *)arg2); break; } #ifdef CONFIG_CHECKPOINT_RESTORE # ifdef CONFIG_X86_X32_ABI case ARCH_MAP_VDSO_X32: - return prctl_map_vdso(&vdso_image_x32, addr); + return prctl_map_vdso(&vdso_image_x32, arg2); # endif # if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION case ARCH_MAP_VDSO_32: - return prctl_map_vdso(&vdso_image_32, addr); + return prctl_map_vdso(&vdso_image_32, arg2); # endif case ARCH_MAP_VDSO_64: - return prctl_map_vdso(&vdso_image_64, addr); + return prctl_map_vdso(&vdso_image_64, arg2); #endif default: @@ -621,10 +649,23 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) return ret; } -long sys_arch_prctl(int code, unsigned long addr) +SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) { - return do_arch_prctl(current, code, addr); + long ret; + + ret = do_arch_prctl_64(current, option, arg2); + if (ret == -EINVAL) + ret = do_arch_prctl_common(current, option, arg2); + + return ret; +} + +#ifdef CONFIG_IA32_EMULATION +COMPAT_SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) +{ + return do_arch_prctl_common(current, option, arg2); } +#endif unsigned long KSTK_ESP(struct task_struct *task) { diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 2364b23ea3e5..f37d18124648 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -396,12 +396,12 @@ static int putreg(struct task_struct *child, if (value >= TASK_SIZE_MAX) return -EIO; /* - * When changing the segment base, use do_arch_prctl + * When changing the segment base, use do_arch_prctl_64 * to set either thread.fs or thread.fsindex and the * corresponding GDT slot. */ if (child->thread.fsbase != value) - return do_arch_prctl(child, ARCH_SET_FS, value); + return do_arch_prctl_64(child, ARCH_SET_FS, value); return 0; case offsetof(struct user_regs_struct,gs_base): /* @@ -410,7 +410,7 @@ static int putreg(struct task_struct *child, if (value >= TASK_SIZE_MAX) return -EIO; if (child->thread.gsbase != value) - return do_arch_prctl(child, ARCH_SET_GS, value); + return do_arch_prctl_64(child, ARCH_SET_GS, value); return 0; #endif } @@ -869,7 +869,7 @@ long arch_ptrace(struct task_struct *child, long request, Works just like arch_prctl, except that the arguments are reversed. */ case PTRACE_ARCH_PRCTL: - ret = do_arch_prctl(child, data, addr); + ret = do_arch_prctl_64(child, data, addr); break; #endif diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index e244c19a2451..2544700a2a87 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -223,6 +223,22 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "P4S800"), }, }, + { /* Handle problems with rebooting on ASUS EeeBook X205TA */ + .callback = set_acpi_reboot, + .ident = "ASUS EeeBook X205TA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X205TA"), + }, + }, + { /* Handle problems with rebooting on ASUS EeeBook X205TAW */ + .callback = set_acpi_reboot, + .ident = "ASUS EeeBook X205TAW", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X205TAW"), + }, + }, /* Certec */ { /* Handle problems with rebooting on Certec BPC600 */ @@ -749,10 +765,11 @@ void machine_crash_shutdown(struct pt_regs *regs) #endif +/* This is the CPU performing the emergency shutdown work. */ +int crashing_cpu = -1; + #if defined(CONFIG_SMP) -/* This keeps a track of which one is crashing cpu. */ -static int crashing_cpu; static nmi_shootdown_cb shootdown_callback; static atomic_t waiting_for_crash_ipi; diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c index 2408c1603438..5ab3895516ac 100644 --- a/arch/x86/kernel/resource.c +++ b/arch/x86/kernel/resource.c @@ -1,5 +1,5 @@ #include <linux/ioport.h> -#include <asm/e820.h> +#include <asm/e820/api.h> static void resource_clip(struct resource *res, resource_size_t start, resource_size_t end) @@ -25,10 +25,10 @@ static void resource_clip(struct resource *res, resource_size_t start, static void remove_e820_regions(struct resource *avail) { int i; - struct e820entry *entry; + struct e820_entry *entry; - for (i = 0; i < e820->nr_map; i++) { - entry = &e820->map[i]; + for (i = 0; i < e820_table->nr_entries; i++) { + entry = &e820_table->entries[i]; resource_clip(avail, entry->addr, entry->addr + entry->size - 1); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 4bf0c8926a1c..603a1669a2ec 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -70,12 +70,13 @@ #include <linux/tboot.h> #include <linux/jiffies.h> +#include <linux/usb/xhci-dbgp.h> #include <video/edid.h> #include <asm/mtrr.h> #include <asm/apic.h> #include <asm/realmode.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mpspec.h> #include <asm/setup.h> #include <asm/efi.h> @@ -119,7 +120,7 @@ * max_low_pfn_mapped: highest direct mapped pfn under 4GB * max_pfn_mapped: highest direct mapped pfn over 4GB * - * The direct mapping only covers E820_RAM regions, so the ranges and gaps are + * The direct mapping only covers E820_TYPE_RAM regions, so the ranges and gaps are * represented by pfn_mapped */ unsigned long max_low_pfn_mapped; @@ -173,14 +174,11 @@ static struct resource bss_resource = { #ifdef CONFIG_X86_32 -/* cpu data as detected by the assembly code in head.S */ -struct cpuinfo_x86 new_cpu_data = { - .wp_works_ok = -1, -}; +/* cpu data as detected by the assembly code in head_32.S */ +struct cpuinfo_x86 new_cpu_data; + /* common cpu data for all cpus */ -struct cpuinfo_x86 boot_cpu_data __read_mostly = { - .wp_works_ok = -1, -}; +struct cpuinfo_x86 boot_cpu_data __read_mostly; EXPORT_SYMBOL(boot_cpu_data); unsigned int def_to_bigsmp; @@ -426,7 +424,7 @@ static void __init parse_setup_data(void) switch (data_type) { case SETUP_E820_EXT: - parse_e820_ext(pa_data, data_len); + e820__memory_setup_extended(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); @@ -441,29 +439,6 @@ static void __init parse_setup_data(void) } } -static void __init e820_reserve_setup_data(void) -{ - struct setup_data *data; - u64 pa_data; - - pa_data = boot_params.hdr.setup_data; - if (!pa_data) - return; - - while (pa_data) { - data = early_memremap(pa_data, sizeof(*data)); - e820_update_range(pa_data, sizeof(*data)+data->len, - E820_RAM, E820_RESERVED_KERN); - pa_data = data->next; - early_memunmap(data, sizeof(*data)); - } - - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); - memcpy(e820_saved, e820, sizeof(struct e820map)); - printk(KERN_INFO "extended physical RAM map:\n"); - e820_print_map("reserve setup_data"); -} - static void __init memblock_x86_reserve_range_setup_data(void) { struct setup_data *data; @@ -756,16 +731,16 @@ static void __init trim_bios_range(void) * since some BIOSes are known to corrupt low memory. See the * Kconfig help text for X86_RESERVE_LOW. */ - e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED); + e820__range_update(0, PAGE_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED); /* * special case: Some BIOSen report the PC BIOS * area (640->1Mb) as ram even though it is not. * take them out. */ - e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); + e820__range_remove(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_TYPE_RAM, 1); - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); + e820__update_table(e820_table); } /* called before trim_bios_range() to spare extra sanitize */ @@ -775,18 +750,18 @@ static void __init e820_add_kernel_range(void) u64 size = __pa_symbol(_end) - start; /* - * Complain if .text .data and .bss are not marked as E820_RAM and + * Complain if .text .data and .bss are not marked as E820_TYPE_RAM and * attempt to fix it by adding the range. We may have a confused BIOS, * or the user may have used memmap=exactmap or memmap=xxM$yyM to * exclude kernel range. If we really are running on top non-RAM, * we will crash later anyways. */ - if (e820_all_mapped(start, start + size, E820_RAM)) + if (e820__mapped_all(start, start + size, E820_TYPE_RAM)) return; - pr_warn(".text .data .bss are not marked as E820_RAM!\n"); - e820_remove_range(start, size, E820_RAM, 0); - e820_add_region(start, size, E820_RAM); + pr_warn(".text .data .bss are not marked as E820_TYPE_RAM!\n"); + e820__range_remove(start, size, E820_TYPE_RAM, 0); + e820__range_add(start, size, E820_TYPE_RAM); } static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; @@ -837,6 +812,26 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) return 0; } +static void __init simple_udelay_calibration(void) +{ + unsigned int tsc_khz, cpu_khz; + unsigned long lpj; + + if (!boot_cpu_has(X86_FEATURE_TSC)) + return; + + cpu_khz = x86_platform.calibrate_cpu(); + tsc_khz = x86_platform.calibrate_tsc(); + + tsc_khz = tsc_khz ? : cpu_khz; + if (!tsc_khz) + return; + + lpj = tsc_khz * 1000; + do_div(lpj, HZ); + loops_per_jiffy = lpj; +} + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -939,7 +934,7 @@ void __init setup_arch(char **cmdline_p) x86_init.oem.arch_setup(); iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1; - setup_memory_map(); + e820__memory_setup(); parse_setup_data(); copy_edd(); @@ -985,6 +980,8 @@ void __init setup_arch(char **cmdline_p) */ x86_configure_nx(); + simple_udelay_calibration(); + parse_early_param(); #ifdef CONFIG_MEMORY_HOTPLUG @@ -1028,9 +1025,8 @@ void __init setup_arch(char **cmdline_p) early_dump_pci_devices(); #endif - /* update the e820_saved too */ - e820_reserve_setup_data(); - finish_e820_parsing(); + e820__reserve_setup_data(); + e820__finish_early_params(); if (efi_enabled(EFI_BOOT)) efi_init(); @@ -1056,11 +1052,11 @@ void __init setup_arch(char **cmdline_p) trim_bios_range(); #ifdef CONFIG_X86_32 if (ppro_with_ram_bug()) { - e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM, - E820_RESERVED); - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); + e820__range_update(0x70000000ULL, 0x40000ULL, E820_TYPE_RAM, + E820_TYPE_RESERVED); + e820__update_table(e820_table); printk(KERN_INFO "fixed physical RAM map:\n"); - e820_print_map("bad_ppro"); + e820__print_table("bad_ppro"); } #else early_gart_iommu_check(); @@ -1070,12 +1066,12 @@ void __init setup_arch(char **cmdline_p) * partially used pages are not usable - thus * we are rounding upwards: */ - max_pfn = e820_end_of_ram_pfn(); + max_pfn = e820__end_of_ram_pfn(); /* update e820 for memory not covered by WB MTRRs */ mtrr_bp_init(); if (mtrr_trim_uncached_memory(max_pfn)) - max_pfn = e820_end_of_ram_pfn(); + max_pfn = e820__end_of_ram_pfn(); max_possible_pfn = max_pfn; @@ -1094,7 +1090,7 @@ void __init setup_arch(char **cmdline_p) /* How many end-of-memory variables you have, grandma! */ /* need this before calling reserve_initrd */ if (max_pfn > (1UL<<(32 - PAGE_SHIFT))) - max_low_pfn = e820_end_of_low_ram_pfn(); + max_low_pfn = e820__end_of_low_ram_pfn(); else max_low_pfn = max_pfn; @@ -1111,7 +1107,7 @@ void __init setup_arch(char **cmdline_p) early_alloc_pgt_buf(); /* - * Need to conclude brk, before memblock_x86_fill() + * Need to conclude brk, before e820__memblock_setup() * it could use memblock_find_in_range, could overlap with * brk area. */ @@ -1120,7 +1116,10 @@ void __init setup_arch(char **cmdline_p) cleanup_highmap(); memblock_set_current_limit(ISA_END_ADDRESS); - memblock_x86_fill(); + e820__memblock_setup(); + + if (!early_xdbc_setup_hardware()) + early_xdbc_register_console(); reserve_bios_regions(); @@ -1137,7 +1136,7 @@ void __init setup_arch(char **cmdline_p) } /* preallocate 4k for mptable mpc */ - early_reserve_e820_mpc_new(); + e820__memblock_alloc_reserved_mpc_new(); #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION setup_bios_corruption_check(); @@ -1226,21 +1225,6 @@ void __init setup_arch(char **cmdline_p) kasan_init(); -#ifdef CONFIG_X86_32 - /* sync back kernel address range */ - clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, - swapper_pg_dir + KERNEL_PGD_BOUNDARY, - KERNEL_PGD_PTRS); - - /* - * sync back low identity map too. It is used for example - * in the 32-bit EFI stub. - */ - clone_pgd_range(initial_page_table, - swapper_pg_dir + KERNEL_PGD_BOUNDARY, - min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); -#endif - tboot_probe(); map_vsyscall(); @@ -1275,12 +1259,12 @@ void __init setup_arch(char **cmdline_p) kvm_guest_init(); - e820_reserve_resources(); - e820_mark_nosave_regions(max_low_pfn); + e820__reserve_resources(); + e820__register_nosave_regions(max_low_pfn); x86_init.resources.reserve_resources(); - e820_setup_gap(); + e820__setup_pci_gap(); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 9820d6d977c6..bb1e8cc0bc84 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -160,7 +160,7 @@ static inline void setup_percpu_segment(int cpu) pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF, 0x2 | DESCTYPE_S, 0x8); gdt.s = 1; - write_gdt_entry(get_cpu_gdt_table(cpu), + write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); #endif } @@ -288,4 +288,25 @@ void __init setup_per_cpu_areas(void) /* Setup cpu initialized, callin, callout masks */ setup_cpu_local_masks(); + +#ifdef CONFIG_X86_32 + /* + * Sync back kernel address range. We want to make sure that + * all kernel mappings, including percpu mappings, are available + * in the smpboot asm. We can't reliably pick up percpu + * mappings using vmalloc_fault(), because exception dispatch + * needs percpu data. + */ + clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); + + /* + * sync back low identity map too. It is used for example + * in the 32-bit EFI stub. + */ + clone_pgd_range(initial_page_table, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); +#endif } diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 396c042e9d0e..cc30a74e4adb 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -846,7 +846,7 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where) task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, me->comm, me->pid, where, frame, regs->ip, regs->sp, regs->orig_ax); - print_vma_addr(" in ", regs->ip); + print_vma_addr(KERN_CONT " in ", regs->ip); pr_cont("\n"); } diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c index ec1f756f9dc9..71beb28600d4 100644 --- a/arch/x86/kernel/signal_compat.c +++ b/arch/x86/kernel/signal_compat.c @@ -151,8 +151,8 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from, if (from->si_signo == SIGSEGV) { if (from->si_code == SEGV_BNDERR) { - compat_uptr_t lower = (unsigned long)&to->si_lower; - compat_uptr_t upper = (unsigned long)&to->si_upper; + compat_uptr_t lower = (unsigned long)from->si_lower; + compat_uptr_t upper = (unsigned long)from->si_upper; put_user_ex(lower, &to->si_lower); put_user_ex(upper, &to->si_upper); } diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index d3c66a15bbde..d798c0da451c 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -33,6 +33,7 @@ #include <asm/mce.h> #include <asm/trace/irq_vectors.h> #include <asm/kexec.h> +#include <asm/virtext.h> /* * Some notes on x86 processor bugs affecting SMP operation: @@ -124,7 +125,7 @@ static bool smp_no_nmi_ipi = false; static void native_smp_send_reschedule(int cpu) { if (unlikely(cpu_is_offline(cpu))) { - WARN_ON(1); + WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu); return; } apic->send_IPI(cpu, RESCHEDULE_VECTOR); @@ -162,6 +163,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) if (raw_smp_processor_id() == atomic_read(&stopping_cpu)) return NMI_HANDLED; + cpu_emergency_vmxoff(); stop_this_cpu(NULL); return NMI_HANDLED; @@ -174,6 +176,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) asmlinkage __visible void smp_reboot_interrupt(void) { ipi_entering_ack_irq(); + cpu_emergency_vmxoff(); stop_this_cpu(NULL); irq_exit(); } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index bd1f1ad35284..f04479a8f74f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -983,7 +983,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) unsigned long timeout; idle->thread.sp = (unsigned long)task_pt_regs(idle); - early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); + early_gdt_descr.address = (unsigned long)get_cpu_gdt_rw(cpu); initial_code = (unsigned long)start_secondary; initial_stack = idle->thread.sp; diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 50215a4b9347..207b8f2582c7 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -17,6 +17,8 @@ #include <linux/uaccess.h> #include <linux/elf.h> +#include <asm/elf.h> +#include <asm/compat.h> #include <asm/ia32.h> #include <asm/syscalls.h> @@ -101,7 +103,7 @@ out: static void find_start_end(unsigned long flags, unsigned long *begin, unsigned long *end) { - if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT)) { + if (!in_compat_syscall() && (flags & MAP_32BIT)) { /* This is usually used needed to map code in small model, so it needs to be in the first 31bit. Limit it to that. This means we need to move the @@ -114,10 +116,11 @@ static void find_start_end(unsigned long flags, unsigned long *begin, if (current->flags & PF_RANDOMIZE) { *begin = randomize_page(*begin, 0x02000000); } - } else { - *begin = current->mm->mmap_legacy_base; - *end = TASK_SIZE; + return; } + + *begin = get_mmap_base(1); + *end = in_compat_syscall() ? tasksize_32bit() : tasksize_64bit(); } unsigned long @@ -176,7 +179,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, return addr; /* for MAP_32BIT mappings we force the legacy mmap base */ - if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT)) + if (!in_compat_syscall() && (flags & MAP_32BIT)) goto bottomup; /* requesting a specific address */ @@ -191,7 +194,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; info.low_limit = PAGE_SIZE; - info.high_limit = mm->mmap_base; + info.high_limit = get_mmap_base(0); info.align_mask = 0; info.align_offset = pgoff << PAGE_SHIFT; if (filp) { diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index b868fa1b812b..d4c8011a2293 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -42,7 +42,7 @@ #include <asm/fixmap.h> #include <asm/proto.h> #include <asm/setup.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/io.h> #include "../realmode/rm/wakeup.h" @@ -68,9 +68,9 @@ void __init tboot_probe(void) * also verify that it is mapped as we expect it before calling * set_fixmap(), to reduce chance of garbage value causing crash */ - if (!e820_any_mapped(boot_params.tboot_addr, - boot_params.tboot_addr, E820_RESERVED)) { - pr_warning("non-0 tboot_addr but it is not of type E820_RESERVED\n"); + if (!e820__mapped_any(boot_params.tboot_addr, + boot_params.tboot_addr, E820_TYPE_RESERVED)) { + pr_warning("non-0 tboot_addr but it is not of type E820_TYPE_RESERVED\n"); return; } @@ -118,12 +118,16 @@ static int map_tboot_page(unsigned long vaddr, unsigned long pfn, pgprot_t prot) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; pgd = pgd_offset(&tboot_mm, vaddr); - pud = pud_alloc(&tboot_mm, pgd, vaddr); + p4d = p4d_alloc(&tboot_mm, pgd, vaddr); + if (!p4d) + return -1; + pud = pud_alloc(&tboot_mm, p4d, vaddr); if (!pud) return -1; pmd = pmd_alloc(&tboot_mm, pud, vaddr); @@ -188,12 +192,12 @@ static int tboot_setup_sleep(void) tboot->num_mac_regions = 0; - for (i = 0; i < e820->nr_map; i++) { - if ((e820->map[i].type != E820_RAM) - && (e820->map[i].type != E820_RESERVED_KERN)) + for (i = 0; i < e820_table->nr_entries; i++) { + if ((e820_table->entries[i].type != E820_TYPE_RAM) + && (e820_table->entries[i].type != E820_TYPE_RESERVED_KERN)) continue; - add_mac_region(e820->map[i].addr, e820->map[i].size); + add_mac_region(e820_table->entries[i].addr, e820_table->entries[i].size); } tboot->acpi_sinfo.kernel_s3_resume_vector = diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index 6c8934406dc9..dcd699baea1b 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -92,10 +92,17 @@ static void set_tls_desc(struct task_struct *p, int idx, cpu = get_cpu(); while (n-- > 0) { - if (LDT_empty(info) || LDT_zero(info)) + if (LDT_empty(info) || LDT_zero(info)) { desc->a = desc->b = 0; - else + } else { fill_ldt(desc, info); + + /* + * Always set the accessed bit so that the CPU + * doesn't try to write to the (read-only) GDT. + */ + desc->type |= 1; + } ++info; ++desc; } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 948443e115c1..3995d3a777d4 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -169,6 +169,37 @@ void ist_end_non_atomic(void) preempt_disable(); } +int is_valid_bugaddr(unsigned long addr) +{ + unsigned short ud; + + if (addr < TASK_SIZE_MAX) + return 0; + + if (probe_kernel_address((unsigned short *)addr, ud)) + return 0; + + return ud == INSN_UD0 || ud == INSN_UD2; +} + +static int fixup_bug(struct pt_regs *regs, int trapnr) +{ + if (trapnr != X86_TRAP_UD) + return 0; + + switch (report_bug(regs->ip, regs)) { + case BUG_TRAP_TYPE_NONE: + case BUG_TRAP_TYPE_BUG: + break; + + case BUG_TRAP_TYPE_WARN: + regs->ip += LEN_UD0; + return 1; + } + + return 0; +} + static nokprobe_inline int do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, struct pt_regs *regs, long error_code) @@ -187,12 +218,15 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, } if (!user_mode(regs)) { - if (!fixup_exception(regs, trapnr)) { - tsk->thread.error_code = error_code; - tsk->thread.trap_nr = trapnr; - die(str, regs, error_code); - } - return 0; + if (fixup_exception(regs, trapnr)) + return 0; + + if (fixup_bug(regs, trapnr)) + return 0; + + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = trapnr; + die(str, regs, error_code); } return -1; @@ -255,7 +289,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx", tsk->comm, tsk->pid, str, regs->ip, regs->sp, error_code); - print_vma_addr(" in ", regs->ip); + print_vma_addr(KERN_CONT " in ", regs->ip); pr_cont("\n"); } @@ -519,7 +553,7 @@ do_general_protection(struct pt_regs *regs, long error_code) pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx", tsk->comm, task_pid_nr(tsk), regs->ip, regs->sp, error_code); - print_vma_addr(" in ", regs->ip); + print_vma_addr(KERN_CONT " in ", regs->ip); pr_cont("\n"); } diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 46bcda4cb1c2..714dfba6a1e7 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -327,9 +327,16 @@ unsigned long long sched_clock(void) { return paravirt_sched_clock(); } + +bool using_native_sched_clock(void) +{ + return pv_time_ops.sched_clock == native_sched_clock; +} #else unsigned long long sched_clock(void) __attribute__((alias("native_sched_clock"))); + +bool using_native_sched_clock(void) { return true; } #endif int check_tsc_unstable(void) @@ -1112,8 +1119,10 @@ static void tsc_cs_mark_unstable(struct clocksource *cs) { if (tsc_unstable) return; + tsc_unstable = 1; - clear_sched_clock_stable(); + if (using_native_sched_clock()) + clear_sched_clock_stable(); disable_sched_clock_irqtime(); pr_info("Marking TSC unstable due to clocksource watchdog\n"); } @@ -1135,18 +1144,20 @@ static struct clocksource clocksource_tsc = { void mark_tsc_unstable(char *reason) { - if (!tsc_unstable) { - tsc_unstable = 1; + if (tsc_unstable) + return; + + tsc_unstable = 1; + if (using_native_sched_clock()) clear_sched_clock_stable(); - disable_sched_clock_irqtime(); - pr_info("Marking TSC unstable due to %s\n", reason); - /* Change only the rating, when not registered */ - if (clocksource_tsc.mult) - clocksource_mark_unstable(&clocksource_tsc); - else { - clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE; - clocksource_tsc.rating = 0; - } + disable_sched_clock_irqtime(); + pr_info("Marking TSC unstable due to %s\n", reason); + /* Change only the rating, when not registered */ + if (clocksource_tsc.mult) { + clocksource_mark_unstable(&clocksource_tsc); + } else { + clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE; + clocksource_tsc.rating = 0; } } @@ -1322,6 +1333,8 @@ static int __init init_tsc_clocksource(void) * the refined calibration and directly register it as a clocksource. */ if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) { + if (boot_cpu_has(X86_FEATURE_ART)) + art_related_clocksource = &clocksource_tsc; clocksource_register_khz(&clocksource_tsc, tsc_khz); return 0; } diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c index 5ed43910e04b..82c6d7f1fd73 100644 --- a/arch/x86/kernel/unwind_frame.c +++ b/arch/x86/kernel/unwind_frame.c @@ -1,6 +1,8 @@ #include <linux/sched.h> #include <linux/sched/task.h> #include <linux/sched/task_stack.h> +#include <linux/interrupt.h> +#include <asm/sections.h> #include <asm/ptrace.h> #include <asm/bitops.h> #include <asm/stacktrace.h> @@ -23,53 +25,53 @@ val; \ }) -static void unwind_dump(struct unwind_state *state, unsigned long *sp) +static void unwind_dump(struct unwind_state *state) { static bool dumped_before = false; bool prev_zero, zero = false; - unsigned long word; + unsigned long word, *sp; + struct stack_info stack_info = {0}; + unsigned long visit_mask = 0; if (dumped_before) return; dumped_before = true; - printk_deferred("unwind stack type:%d next_sp:%p mask:%lx graph_idx:%d\n", + printk_deferred("unwind stack type:%d next_sp:%p mask:0x%lx graph_idx:%d\n", state->stack_info.type, state->stack_info.next_sp, state->stack_mask, state->graph_idx); - for (sp = state->orig_sp; sp < state->stack_info.end; sp++) { - word = READ_ONCE_NOCHECK(*sp); + for (sp = state->orig_sp; sp; sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { + if (get_stack_info(sp, state->task, &stack_info, &visit_mask)) + break; - prev_zero = zero; - zero = word == 0; + for (; sp < stack_info.end; sp++) { - if (zero) { - if (!prev_zero) - printk_deferred("%p: %016x ...\n", sp, 0); - continue; - } + word = READ_ONCE_NOCHECK(*sp); + + prev_zero = zero; + zero = word == 0; + + if (zero) { + if (!prev_zero) + printk_deferred("%p: %0*x ...\n", + sp, BITS_PER_LONG/4, 0); + continue; + } - printk_deferred("%p: %016lx (%pB)\n", sp, word, (void *)word); + printk_deferred("%p: %0*lx (%pB)\n", + sp, BITS_PER_LONG/4, word, (void *)word); + } } } unsigned long unwind_get_return_address(struct unwind_state *state) { - unsigned long addr; - unsigned long *addr_p = unwind_get_return_address_ptr(state); - if (unwind_done(state)) return 0; - if (state->regs && user_mode(state->regs)) - return 0; - - addr = READ_ONCE_TASK_STACK(state->task, *addr_p); - addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr, - addr_p); - - return __kernel_text_address(addr) ? addr : 0; + return __kernel_text_address(state->ip) ? state->ip : 0; } EXPORT_SYMBOL_GPL(unwind_get_return_address); @@ -82,19 +84,68 @@ static size_t regs_size(struct pt_regs *regs) return sizeof(*regs); } +static bool in_entry_code(unsigned long ip) +{ + char *addr = (char *)ip; + + if (addr >= __entry_text_start && addr < __entry_text_end) + return true; + +#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) + if (addr >= __irqentry_text_start && addr < __irqentry_text_end) + return true; +#endif + + return false; +} + +static inline unsigned long *last_frame(struct unwind_state *state) +{ + return (unsigned long *)task_pt_regs(state->task) - 2; +} + +#ifdef CONFIG_X86_32 +#define GCC_REALIGN_WORDS 3 +#else +#define GCC_REALIGN_WORDS 1 +#endif + +static inline unsigned long *last_aligned_frame(struct unwind_state *state) +{ + return last_frame(state) - GCC_REALIGN_WORDS; +} + static bool is_last_task_frame(struct unwind_state *state) { - unsigned long bp = (unsigned long)state->bp; - unsigned long regs = (unsigned long)task_pt_regs(state->task); + unsigned long *last_bp = last_frame(state); + unsigned long *aligned_bp = last_aligned_frame(state); /* * We have to check for the last task frame at two different locations * because gcc can occasionally decide to realign the stack pointer and - * change the offset of the stack frame by a word in the prologue of a - * function called by head/entry code. + * change the offset of the stack frame in the prologue of a function + * called by head/entry code. Examples: + * + * <start_secondary>: + * push %edi + * lea 0x8(%esp),%edi + * and $0xfffffff8,%esp + * pushl -0x4(%edi) + * push %ebp + * mov %esp,%ebp + * + * <x86_64_start_kernel>: + * lea 0x8(%rsp),%r10 + * and $0xfffffffffffffff0,%rsp + * pushq -0x8(%r10) + * push %rbp + * mov %rsp,%rbp + * + * Note that after aligning the stack, it pushes a duplicate copy of + * the return address before pushing the frame pointer. */ - return bp == regs - FRAME_HEADER_SIZE || - bp == regs - FRAME_HEADER_SIZE - sizeof(long); + return (state->bp == last_bp || + (state->bp == aligned_bp && *(aligned_bp+1) == *(last_bp+1))); } /* @@ -111,26 +162,70 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp) return (struct pt_regs *)(regs & ~0x1); } -static bool update_stack_state(struct unwind_state *state, void *addr, - size_t len) +static bool update_stack_state(struct unwind_state *state, + unsigned long *next_bp) { struct stack_info *info = &state->stack_info; - enum stack_type orig_type = info->type; + enum stack_type prev_type = info->type; + struct pt_regs *regs; + unsigned long *frame, *prev_frame_end, *addr_p, addr; + size_t len; + + if (state->regs) + prev_frame_end = (void *)state->regs + regs_size(state->regs); + else + prev_frame_end = (void *)state->bp + FRAME_HEADER_SIZE; + + /* Is the next frame pointer an encoded pointer to pt_regs? */ + regs = decode_frame_pointer(next_bp); + if (regs) { + frame = (unsigned long *)regs; + len = regs_size(regs); + state->got_irq = true; + } else { + frame = next_bp; + len = FRAME_HEADER_SIZE; + } /* - * If addr isn't on the current stack, switch to the next one. + * If the next bp isn't on the current stack, switch to the next one. * * We may have to traverse multiple stacks to deal with the possibility - * that 'info->next_sp' could point to an empty stack and 'addr' could - * be on a subsequent stack. + * that info->next_sp could point to an empty stack and the next bp + * could be on a subsequent stack. */ - while (!on_stack(info, addr, len)) + while (!on_stack(info, frame, len)) if (get_stack_info(info->next_sp, state->task, info, &state->stack_mask)) return false; - if (!state->orig_sp || info->type != orig_type) - state->orig_sp = addr; + /* Make sure it only unwinds up and doesn't overlap the prev frame: */ + if (state->orig_sp && state->stack_info.type == prev_type && + frame < prev_frame_end) + return false; + + /* Move state to the next frame: */ + if (regs) { + state->regs = regs; + state->bp = NULL; + } else { + state->bp = next_bp; + state->regs = NULL; + } + + /* Save the return address: */ + if (state->regs && user_mode(state->regs)) + state->ip = 0; + else { + addr_p = unwind_get_return_address_ptr(state); + addr = READ_ONCE_TASK_STACK(state->task, *addr_p); + state->ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, + addr, addr_p); + } + + /* Save the original stack pointer for unwind_dump(): */ + if (!state->orig_sp) + state->orig_sp = frame; return true; } @@ -138,14 +233,12 @@ static bool update_stack_state(struct unwind_state *state, void *addr, bool unwind_next_frame(struct unwind_state *state) { struct pt_regs *regs; - unsigned long *next_bp, *next_frame; - size_t next_len; - enum stack_type prev_type = state->stack_info.type; + unsigned long *next_bp; if (unwind_done(state)) return false; - /* have we reached the end? */ + /* Have we reached the end? */ if (state->regs && user_mode(state->regs)) goto the_end; @@ -173,54 +266,19 @@ bool unwind_next_frame(struct unwind_state *state) */ state->regs = regs; state->bp = NULL; + state->ip = 0; return true; } - /* get the next frame pointer */ + /* Get the next frame pointer: */ if (state->regs) next_bp = (unsigned long *)state->regs->bp; else - next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp); - - /* is the next frame pointer an encoded pointer to pt_regs? */ - regs = decode_frame_pointer(next_bp); - if (regs) { - next_frame = (unsigned long *)regs; - next_len = sizeof(*regs); - } else { - next_frame = next_bp; - next_len = FRAME_HEADER_SIZE; - } - - /* make sure the next frame's data is accessible */ - if (!update_stack_state(state, next_frame, next_len)) { - /* - * Don't warn on bad regs->bp. An interrupt in entry code - * might cause a false positive warning. - */ - if (state->regs) - goto the_end; + next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task, *state->bp); + /* Move to the next frame if it's safe: */ + if (!update_stack_state(state, next_bp)) goto bad_address; - } - - /* Make sure it only unwinds up and doesn't overlap the last frame: */ - if (state->stack_info.type == prev_type) { - if (state->regs && (void *)next_frame < (void *)state->regs + regs_size(state->regs)) - goto bad_address; - - if (state->bp && (void *)next_frame < (void *)state->bp + FRAME_HEADER_SIZE) - goto bad_address; - } - - /* move to the next frame */ - if (regs) { - state->regs = regs; - state->bp = NULL; - } else { - state->bp = next_bp; - state->regs = NULL; - } return true; @@ -237,18 +295,29 @@ bad_address: if (state->task != current) goto the_end; + /* + * Don't warn if the unwinder got lost due to an interrupt in entry + * code or in the C handler before the first frame pointer got set up: + */ + if (state->got_irq && in_entry_code(state->ip)) + goto the_end; + if (state->regs && + state->regs->sp >= (unsigned long)last_aligned_frame(state) && + state->regs->sp < (unsigned long)task_pt_regs(state->task)) + goto the_end; + if (state->regs) { printk_deferred_once(KERN_WARNING "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n", state->regs, state->task->comm, - state->task->pid, next_frame); - unwind_dump(state, (unsigned long *)state->regs); + state->task->pid, next_bp); + unwind_dump(state); } else { printk_deferred_once(KERN_WARNING "WARNING: kernel stack frame pointer at %p in %s:%d has bad value %p\n", state->bp, state->task->comm, - state->task->pid, next_frame); - unwind_dump(state, state->bp); + state->task->pid, next_bp); + unwind_dump(state); } the_end: state->stack_info.type = STACK_TYPE_UNKNOWN; @@ -259,35 +328,24 @@ EXPORT_SYMBOL_GPL(unwind_next_frame); void __unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs, unsigned long *first_frame) { - unsigned long *bp, *frame; - size_t len; + unsigned long *bp; memset(state, 0, sizeof(*state)); state->task = task; + state->got_irq = (regs); - /* don't even attempt to start from user mode regs */ + /* Don't even attempt to start from user mode regs: */ if (regs && user_mode(regs)) { state->stack_info.type = STACK_TYPE_UNKNOWN; return; } - /* set up the starting stack frame */ bp = get_frame_pointer(task, regs); - regs = decode_frame_pointer(bp); - if (regs) { - state->regs = regs; - frame = (unsigned long *)regs; - len = sizeof(*regs); - } else { - state->bp = bp; - frame = bp; - len = FRAME_HEADER_SIZE; - } - /* initialize stack info and make sure the frame data is accessible */ - get_stack_info(frame, state->task, &state->stack_info, + /* Initialize stack info and make sure the frame data is accessible: */ + get_stack_info(bp, state->task, &state->stack_info, &state->stack_mask); - update_stack_state(state, frame, len); + update_stack_state(state, bp); /* * The caller can provide the address of the first frame directly diff --git a/arch/x86/kernel/unwind_guess.c b/arch/x86/kernel/unwind_guess.c index 22881ddcbb9f..039f36738e49 100644 --- a/arch/x86/kernel/unwind_guess.c +++ b/arch/x86/kernel/unwind_guess.c @@ -34,7 +34,7 @@ bool unwind_next_frame(struct unwind_state *state) return true; } - state->sp = info->next_sp; + state->sp = PTR_ALIGN(info->next_sp, sizeof(long)); } while (!get_stack_info(state->sp, state->task, info, &state->stack_mask)); @@ -49,7 +49,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, memset(state, 0, sizeof(*state)); state->task = task; - state->sp = first_frame; + state->sp = PTR_ALIGN(first_frame, sizeof(long)); get_stack_info(first_frame, state->task, &state->stack_info, &state->stack_mask); diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 23ee89ce59a9..7924a5356c8a 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -164,6 +164,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) struct vm_area_struct *vma; spinlock_t *ptl; pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -173,7 +174,10 @@ static void mark_screen_rdonly(struct mm_struct *mm) pgd = pgd_offset(mm, 0xA0000); if (pgd_none_or_clear_bad(pgd)) goto out; - pud = pud_offset(pgd, 0xA0000); + p4d = p4d_offset(pgd, 0xA0000); + if (p4d_none_or_clear_bad(p4d)) + goto out; + pud = pud_offset(p4d, 0xA0000); if (pud_none_or_clear_bad(pud)) goto out; pmd = pmd_offset(pud, 0xA0000); @@ -193,7 +197,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) pte_unmap_unlock(pte, ptl); out: up_write(&mm->mmap_sem); - flush_tlb(); + flush_tlb_mm_range(mm, 0xA0000, 0xA0000 + 32*PAGE_SIZE, 0UL); } diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index c74ae9ce8dc4..c8a3b61be0aa 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -146,6 +146,7 @@ SECTIONS _edata = .; } :data + BUG_TABLE . = ALIGN(PAGE_SIZE); __vvar_page = .; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 11a93f005268..a088b2c47f73 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -14,7 +14,7 @@ #include <asm/mpspec.h> #include <asm/setup.h> #include <asm/apic.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/time.h> #include <asm/irq.h> #include <asm/io_apic.h> @@ -38,7 +38,7 @@ struct x86_init_ops x86_init __initdata = { .resources = { .probe_roms = probe_roms, .reserve_resources = reserve_standard_io_resources, - .memory_setup = default_machine_specific_memory_setup, + .memory_setup = e820__memory_setup_default, }, .mpparse = { diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 73ea24d4f119..047b17a26269 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -657,6 +657,9 @@ void kvm_pic_destroy(struct kvm *kvm) { struct kvm_pic *vpic = kvm->arch.vpic; + if (!vpic) + return; + kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_master); kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_slave); kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_eclr); diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 6e219e5c07d2..289270a6aecb 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -635,6 +635,9 @@ void kvm_ioapic_destroy(struct kvm *kvm) { struct kvm_ioapic *ioapic = kvm->arch.vioapic; + if (!ioapic) + return; + cancel_delayed_work_sync(&ioapic->eoi_inject); kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &ioapic->dev); kvm->arch.vioapic = NULL; diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c index 37942e419c32..60168cdd0546 100644 --- a/arch/x86/kvm/page_track.c +++ b/arch/x86/kvm/page_track.c @@ -160,6 +160,14 @@ bool kvm_page_track_is_active(struct kvm_vcpu *vcpu, gfn_t gfn, return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]); } +void kvm_page_track_cleanup(struct kvm *kvm) +{ + struct kvm_page_track_notifier_head *head; + + head = &kvm->arch.track_notifier_head; + cleanup_srcu_struct(&head->track_srcu); +} + void kvm_page_track_init(struct kvm *kvm) { struct kvm_page_track_notifier_head *head; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index d1efe2c62b3f..5f48f62b8dc2 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -741,7 +741,6 @@ static int svm_hardware_enable(void) struct svm_cpu_data *sd; uint64_t efer; - struct desc_ptr gdt_descr; struct desc_struct *gdt; int me = raw_smp_processor_id(); @@ -763,8 +762,7 @@ static int svm_hardware_enable(void) sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; sd->next_asid = sd->max_asid + 1; - native_store_gdt(&gdt_descr); - gdt = (struct desc_struct *)gdt_descr.address; + gdt = get_current_gdt_rw(); sd->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); wrmsrl(MSR_EFER, efer | EFER_SVME); @@ -1379,6 +1377,9 @@ static void avic_vm_destroy(struct kvm *kvm) unsigned long flags; struct kvm_arch *vm_data = &kvm->arch; + if (!avic) + return; + avic_free_vm_id(vm_data->avic_vm_id); if (vm_data->avic_logical_id_table_page) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 283aa8601833..1a471e5f963f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -935,7 +935,6 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs); * when a CPU is brought down, and we need to VMCLEAR all VMCSs loaded on it. */ static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu); -static DEFINE_PER_CPU(struct desc_ptr, host_gdt); /* * We maintian a per-CPU linked-list of vCPU, so in wakeup_handler() we @@ -1239,6 +1238,11 @@ static inline bool cpu_has_vmx_invvpid_global(void) return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT; } +static inline bool cpu_has_vmx_invvpid(void) +{ + return vmx_capability.vpid & VMX_VPID_INVVPID_BIT; +} + static inline bool cpu_has_vmx_ept(void) { return vmcs_config.cpu_based_2nd_exec_ctrl & @@ -2052,14 +2056,13 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) */ static unsigned long segment_base(u16 selector) { - struct desc_ptr *gdt = this_cpu_ptr(&host_gdt); struct desc_struct *table; unsigned long v; if (!(selector & ~SEGMENT_RPL_MASK)) return 0; - table = (struct desc_struct *)gdt->address; + table = get_current_gdt_ro(); if ((selector & SEGMENT_TI_MASK) == SEGMENT_LDT) { u16 ldt_selector = kvm_read_ldt(); @@ -2164,7 +2167,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) #endif if (vmx->host_state.msr_host_bndcfgs) wrmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs); - load_gdt(this_cpu_ptr(&host_gdt)); + load_fixmap_gdt(raw_smp_processor_id()); } static void vmx_load_host_state(struct vcpu_vmx *vmx) @@ -2266,7 +2269,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) } if (!already_loaded) { - struct desc_ptr *gdt = this_cpu_ptr(&host_gdt); + void *gdt = get_current_gdt_ro(); unsigned long sysenter_esp; kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); @@ -2277,7 +2280,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) */ vmcs_writel(HOST_TR_BASE, (unsigned long)this_cpu_ptr(&cpu_tss)); - vmcs_writel(HOST_GDTR_BASE, gdt->address); + vmcs_writel(HOST_GDTR_BASE, (unsigned long)gdt); /* 22.2.4 */ /* * VM exits change the host TR limit to 0x67 after a VM @@ -2753,7 +2756,6 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) SECONDARY_EXEC_RDTSCP | SECONDARY_EXEC_DESC | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | - SECONDARY_EXEC_ENABLE_VPID | SECONDARY_EXEC_APIC_REGISTER_VIRT | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | SECONDARY_EXEC_WBINVD_EXITING | @@ -2781,10 +2783,12 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) * though it is treated as global context. The alternative is * not failing the single-context invvpid, and it is worse. */ - if (enable_vpid) + if (enable_vpid) { + vmx->nested.nested_vmx_secondary_ctls_high |= + SECONDARY_EXEC_ENABLE_VPID; vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT | VMX_VPID_EXTENT_SUPPORTED_MASK; - else + } else vmx->nested.nested_vmx_vpid_caps = 0; if (enable_unrestricted_guest) @@ -3465,8 +3469,6 @@ static int hardware_enable(void) ept_sync_global(); } - native_store_gdt(this_cpu_ptr(&host_gdt)); - return 0; } @@ -4024,6 +4026,12 @@ static void vmx_flush_tlb(struct kvm_vcpu *vcpu) __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid); } +static void vmx_flush_tlb_ept_only(struct kvm_vcpu *vcpu) +{ + if (enable_ept) + vmx_flush_tlb(vcpu); +} + static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu) { ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits; @@ -6517,8 +6525,10 @@ static __init int hardware_setup(void) if (boot_cpu_has(X86_FEATURE_NX)) kvm_enable_efer_bits(EFER_NX); - if (!cpu_has_vmx_vpid()) + if (!cpu_has_vmx_vpid() || !cpu_has_vmx_invvpid() || + !(cpu_has_vmx_invvpid_single() || cpu_has_vmx_invvpid_global())) enable_vpid = 0; + if (!cpu_has_vmx_shadow_vmcs()) enable_shadow_vmcs = 0; if (enable_shadow_vmcs) @@ -7258,9 +7268,8 @@ static int handle_vmoff(struct kvm_vcpu *vcpu) static int handle_vmclear(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); + u32 zero = 0; gpa_t vmptr; - struct vmcs12 *vmcs12; - struct page *page; if (!nested_vmx_check_permission(vcpu)) return 1; @@ -7271,22 +7280,9 @@ static int handle_vmclear(struct kvm_vcpu *vcpu) if (vmptr == vmx->nested.current_vmptr) nested_release_vmcs12(vmx); - page = nested_get_page(vcpu, vmptr); - if (page == NULL) { - /* - * For accurate processor emulation, VMCLEAR beyond available - * physical memory should do nothing at all. However, it is - * possible that a nested vmx bug, not a guest hypervisor bug, - * resulted in this case, so let's shut down before doing any - * more damage: - */ - kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); - return 1; - } - vmcs12 = kmap(page); - vmcs12->launch_state = 0; - kunmap(page); - nested_release_page(page); + kvm_vcpu_write_guest(vcpu, + vmptr + offsetof(struct vmcs12, launch_state), + &zero, sizeof(zero)); nested_free_vmcs02(vmx, vmptr); @@ -8198,6 +8194,9 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES); case EXIT_REASON_PREEMPTION_TIMER: return false; + case EXIT_REASON_PML_FULL: + /* We don't expose PML support to L1. */ + return false; default: return true; } @@ -8515,7 +8514,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) && kvm_vmx_exit_handlers[exit_reason]) return kvm_vmx_exit_handlers[exit_reason](vcpu); else { - WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_reason); + vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n", + exit_reason); kvm_queue_exception(vcpu, UD_VECTOR); return 1; } @@ -8561,6 +8561,7 @@ static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set) } else { sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; + vmx_flush_tlb_ept_only(vcpu); } vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control); @@ -8586,8 +8587,10 @@ static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa) */ if (!is_guest_mode(vcpu) || !nested_cpu_has2(get_vmcs12(&vmx->vcpu), - SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) { vmcs_write64(APIC_ACCESS_ADDR, hpa); + vmx_flush_tlb_ept_only(vcpu); + } } static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr) @@ -9694,10 +9697,8 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu, return false; page = nested_get_page(vcpu, vmcs12->msr_bitmap); - if (!page) { - WARN_ON(1); + if (!page) return false; - } msr_bitmap_l1 = (unsigned long *)kmap(page); memset(msr_bitmap_l0, 0xff, PAGE_SIZE); @@ -9990,7 +9991,6 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, { struct vcpu_vmx *vmx = to_vmx(vcpu); u32 exec_control; - bool nested_ept_enabled = false; vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector); vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector); @@ -10137,8 +10137,6 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, vmcs12->guest_intr_status); } - nested_ept_enabled = (exec_control & SECONDARY_EXEC_ENABLE_EPT) != 0; - /* * Write an illegal value to APIC_ACCESS_ADDR. Later, * nested_get_vmcs12_pages will either fix it up or @@ -10268,9 +10266,24 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, } + if (enable_pml) { + /* + * Conceptually we want to copy the PML address and index from + * vmcs01 here, and then back to vmcs01 on nested vmexit. But, + * since we always flush the log on each vmexit, this happens + * to be equivalent to simply resetting the fields in vmcs02. + */ + ASSERT(vmx->pml_pg); + vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); + vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); + } + if (nested_cpu_has_ept(vmcs12)) { kvm_mmu_unload(vcpu); nested_ept_init_mmu_context(vcpu); + } else if (nested_cpu_has2(vmcs12, + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) { + vmx_flush_tlb_ept_only(vcpu); } /* @@ -10298,12 +10311,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, vmx_set_efer(vcpu, vcpu->arch.efer); /* Shadow page tables on either EPT or shadow page tables. */ - if (nested_vmx_load_cr3(vcpu, vmcs12->guest_cr3, nested_ept_enabled, + if (nested_vmx_load_cr3(vcpu, vmcs12->guest_cr3, nested_cpu_has_ept(vmcs12), entry_failure_code)) return 1; - kvm_mmu_reset_context(vcpu); - if (!enable_ept) vcpu->arch.walk_mmu->inject_page_fault = vmx_inject_page_fault_nested; @@ -11072,6 +11083,10 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, vmx->nested.change_vmcs01_virtual_x2apic_mode = false; vmx_set_virtual_x2apic_mode(vcpu, vcpu->arch.apic_base & X2APIC_ENABLE); + } else if (!nested_cpu_has_ept(vmcs12) && + nested_cpu_has2(vmcs12, + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) { + vmx_flush_tlb_ept_only(vcpu); } /* This is needed for same reason as it was needed in prepare_vmcs02 */ @@ -11121,8 +11136,10 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, */ static void vmx_leave_nested(struct kvm_vcpu *vcpu) { - if (is_guest_mode(vcpu)) + if (is_guest_mode(vcpu)) { + to_vmx(vcpu)->nested.nested_run_pending = 0; nested_vmx_vmexit(vcpu, -1, 0, 0); + } free_nested(to_vmx(vcpu)); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1faf620a6fdc..ccbd45ecd41a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8153,11 +8153,12 @@ void kvm_arch_destroy_vm(struct kvm *kvm) if (kvm_x86_ops->vm_destroy) kvm_x86_ops->vm_destroy(kvm); kvm_iommu_unmap_guest(kvm); - kfree(kvm->arch.vpic); - kfree(kvm->arch.vioapic); + kvm_pic_destroy(kvm); + kvm_ioapic_destroy(kvm); kvm_free_vcpus(kvm); kvfree(rcu_dereference_check(kvm->arch.apic_map, 1)); kvm_mmu_uninit_vm(kvm); + kvm_page_track_cleanup(kvm); } void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, @@ -8566,11 +8567,11 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, { struct x86_exception fault; - trace_kvm_async_pf_ready(work->arch.token, work->gva); if (work->wakeup_all) work->arch.token = ~0; /* broadcast wakeup */ else kvm_del_async_pf_gfn(vcpu, work->arch.gfn); + trace_kvm_async_pf_ready(work->arch.token, work->gva); if ((vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED) && !apf_put_user(vcpu, KVM_PV_REASON_PAGE_READY)) { diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index d3289d7e78fa..99472698c931 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -67,7 +67,7 @@ #include <asm/pgtable.h> #include <asm/desc.h> #include <asm/setup.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mce.h> #include <asm/io.h> #include <asm/fpu/api.h> @@ -994,7 +994,9 @@ static struct clock_event_device lguest_clockevent = { .mult = 1, .shift = 0, .min_delta_ns = LG_CLOCK_MIN_DELTA, + .min_delta_ticks = LG_CLOCK_MIN_DELTA, .max_delta_ns = LG_CLOCK_MAX_DELTA, + .max_delta_ticks = LG_CLOCK_MAX_DELTA, }; /* @@ -1178,9 +1180,9 @@ static __init char *lguest_memory_setup(void) * The Linux bootloader header contains an "e820" memory map: the * Launcher populated the first entry with our memory limit. */ - e820_add_region(boot_params.e820_map[0].addr, - boot_params.e820_map[0].size, - boot_params.e820_map[0].type); + e820__range_add(boot_params.e820_table[0].addr, + boot_params.e820_table[0].size, + boot_params.e820_table[0].type); /* This string is for the boot messages. */ return "LGUEST"; diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S index 5e2af3a88cf5..81b1635d67de 100644 --- a/arch/x86/lib/clear_page_64.S +++ b/arch/x86/lib/clear_page_64.S @@ -14,20 +14,15 @@ * Zero a page. * %rdi - page */ -ENTRY(clear_page) - - ALTERNATIVE_2 "jmp clear_page_orig", "", X86_FEATURE_REP_GOOD, \ - "jmp clear_page_c_e", X86_FEATURE_ERMS - +ENTRY(clear_page_rep) movl $4096/8,%ecx xorl %eax,%eax rep stosq ret -ENDPROC(clear_page) -EXPORT_SYMBOL(clear_page) +ENDPROC(clear_page_rep) +EXPORT_SYMBOL_GPL(clear_page_rep) ENTRY(clear_page_orig) - xorl %eax,%eax movl $4096/64,%ecx .p2align 4 @@ -47,10 +42,12 @@ ENTRY(clear_page_orig) nop ret ENDPROC(clear_page_orig) +EXPORT_SYMBOL_GPL(clear_page_orig) -ENTRY(clear_page_c_e) +ENTRY(clear_page_erms) movl $4096,%ecx xorl %eax,%eax rep stosb ret -ENDPROC(clear_page_c_e) +ENDPROC(clear_page_erms) +EXPORT_SYMBOL_GPL(clear_page_erms) diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index a8e91ae89fb3..29df077cb089 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c @@ -93,6 +93,13 @@ static void delay_mwaitx(unsigned long __loops) { u64 start, end, delay, loops = __loops; + /* + * Timer value of 0 causes MWAITX to wait indefinitely, unless there + * is a store on the memory monitored by MONITORX. + */ + if (loops == 0) + return; + start = rdtsc_ordered(); for (;;) { diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c index 121f59c6ee54..5761a4f19455 100644 --- a/arch/x86/lib/kaslr.c +++ b/arch/x86/lib/kaslr.c @@ -8,7 +8,7 @@ #include <asm/kaslr.h> #include <asm/msr.h> #include <asm/archrandom.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/io.h> /* diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index 779782f58324..9a53a06e5a3e 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S @@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(memcpy_mcsafe_unrolled) _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail) _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail) _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail) - _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail) + _ASM_EXTABLE_FAULT(.L_cache_w2, .L_memcpy_mcsafe_fail) _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail) _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail) _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail) diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index c074799bddae..c8c6ad0d58b8 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -4,12 +4,9 @@ * For licencing details see kernel-base/COPYING */ -#include <linux/highmem.h> +#include <linux/uaccess.h> #include <linux/export.h> -#include <asm/word-at-a-time.h> -#include <linux/sched.h> - /* * We rely on the nested NMI work to allow atomic faults from the NMI path; the * nested NMI paths are careful to preserve CR2. @@ -34,52 +31,3 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) return ret; } EXPORT_SYMBOL_GPL(copy_from_user_nmi); - -/** - * copy_to_user: - Copy a block of data into user space. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from kernel space to user space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -unsigned long _copy_to_user(void __user *to, const void *from, unsigned n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); - return n; -} -EXPORT_SYMBOL(_copy_to_user); - -/** - * copy_from_user: - Copy a block of data from user space. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * Copy data from user space to kernel space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -unsigned long _copy_from_user(void *to, const void __user *from, unsigned n) -{ - if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); - else - memset(to, 0, n); - return n; -} -EXPORT_SYMBOL(_copy_from_user); diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 1f65ff6540f0..bd057a4ffe6e 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -5,12 +5,7 @@ * Copyright 1997 Andi Kleen <ak@muc.de> * Copyright 1997 Linus Torvalds */ -#include <linux/mm.h> -#include <linux/highmem.h> -#include <linux/blkdev.h> #include <linux/export.h> -#include <linux/backing-dev.h> -#include <linux/interrupt.h> #include <linux/uaccess.h> #include <asm/mmx.h> #include <asm/asm.h> @@ -201,197 +196,6 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size) return size; } -static unsigned long -__copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size) -{ - int d0, d1; - __asm__ __volatile__( - " .align 2,0x90\n" - "0: movl 32(%4), %%eax\n" - " cmpl $67, %0\n" - " jbe 2f\n" - "1: movl 64(%4), %%eax\n" - " .align 2,0x90\n" - "2: movl 0(%4), %%eax\n" - "21: movl 4(%4), %%edx\n" - " movl %%eax, 0(%3)\n" - " movl %%edx, 4(%3)\n" - "3: movl 8(%4), %%eax\n" - "31: movl 12(%4),%%edx\n" - " movl %%eax, 8(%3)\n" - " movl %%edx, 12(%3)\n" - "4: movl 16(%4), %%eax\n" - "41: movl 20(%4), %%edx\n" - " movl %%eax, 16(%3)\n" - " movl %%edx, 20(%3)\n" - "10: movl 24(%4), %%eax\n" - "51: movl 28(%4), %%edx\n" - " movl %%eax, 24(%3)\n" - " movl %%edx, 28(%3)\n" - "11: movl 32(%4), %%eax\n" - "61: movl 36(%4), %%edx\n" - " movl %%eax, 32(%3)\n" - " movl %%edx, 36(%3)\n" - "12: movl 40(%4), %%eax\n" - "71: movl 44(%4), %%edx\n" - " movl %%eax, 40(%3)\n" - " movl %%edx, 44(%3)\n" - "13: movl 48(%4), %%eax\n" - "81: movl 52(%4), %%edx\n" - " movl %%eax, 48(%3)\n" - " movl %%edx, 52(%3)\n" - "14: movl 56(%4), %%eax\n" - "91: movl 60(%4), %%edx\n" - " movl %%eax, 56(%3)\n" - " movl %%edx, 60(%3)\n" - " addl $-64, %0\n" - " addl $64, %4\n" - " addl $64, %3\n" - " cmpl $63, %0\n" - " ja 0b\n" - "5: movl %0, %%eax\n" - " shrl $2, %0\n" - " andl $3, %%eax\n" - " cld\n" - "6: rep; movsl\n" - " movl %%eax,%0\n" - "7: rep; movsb\n" - "8:\n" - ".section .fixup,\"ax\"\n" - "9: lea 0(%%eax,%0,4),%0\n" - "16: pushl %0\n" - " pushl %%eax\n" - " xorl %%eax,%%eax\n" - " rep; stosb\n" - " popl %%eax\n" - " popl %0\n" - " jmp 8b\n" - ".previous\n" - _ASM_EXTABLE(0b,16b) - _ASM_EXTABLE(1b,16b) - _ASM_EXTABLE(2b,16b) - _ASM_EXTABLE(21b,16b) - _ASM_EXTABLE(3b,16b) - _ASM_EXTABLE(31b,16b) - _ASM_EXTABLE(4b,16b) - _ASM_EXTABLE(41b,16b) - _ASM_EXTABLE(10b,16b) - _ASM_EXTABLE(51b,16b) - _ASM_EXTABLE(11b,16b) - _ASM_EXTABLE(61b,16b) - _ASM_EXTABLE(12b,16b) - _ASM_EXTABLE(71b,16b) - _ASM_EXTABLE(13b,16b) - _ASM_EXTABLE(81b,16b) - _ASM_EXTABLE(14b,16b) - _ASM_EXTABLE(91b,16b) - _ASM_EXTABLE(6b,9b) - _ASM_EXTABLE(7b,16b) - : "=&c"(size), "=&D" (d0), "=&S" (d1) - : "1"(to), "2"(from), "0"(size) - : "eax", "edx", "memory"); - return size; -} - -/* - * Non Temporal Hint version of __copy_user_zeroing_intel. It is cache aware. - * hyoshiok@miraclelinux.com - */ - -static unsigned long __copy_user_zeroing_intel_nocache(void *to, - const void __user *from, unsigned long size) -{ - int d0, d1; - - __asm__ __volatile__( - " .align 2,0x90\n" - "0: movl 32(%4), %%eax\n" - " cmpl $67, %0\n" - " jbe 2f\n" - "1: movl 64(%4), %%eax\n" - " .align 2,0x90\n" - "2: movl 0(%4), %%eax\n" - "21: movl 4(%4), %%edx\n" - " movnti %%eax, 0(%3)\n" - " movnti %%edx, 4(%3)\n" - "3: movl 8(%4), %%eax\n" - "31: movl 12(%4),%%edx\n" - " movnti %%eax, 8(%3)\n" - " movnti %%edx, 12(%3)\n" - "4: movl 16(%4), %%eax\n" - "41: movl 20(%4), %%edx\n" - " movnti %%eax, 16(%3)\n" - " movnti %%edx, 20(%3)\n" - "10: movl 24(%4), %%eax\n" - "51: movl 28(%4), %%edx\n" - " movnti %%eax, 24(%3)\n" - " movnti %%edx, 28(%3)\n" - "11: movl 32(%4), %%eax\n" - "61: movl 36(%4), %%edx\n" - " movnti %%eax, 32(%3)\n" - " movnti %%edx, 36(%3)\n" - "12: movl 40(%4), %%eax\n" - "71: movl 44(%4), %%edx\n" - " movnti %%eax, 40(%3)\n" - " movnti %%edx, 44(%3)\n" - "13: movl 48(%4), %%eax\n" - "81: movl 52(%4), %%edx\n" - " movnti %%eax, 48(%3)\n" - " movnti %%edx, 52(%3)\n" - "14: movl 56(%4), %%eax\n" - "91: movl 60(%4), %%edx\n" - " movnti %%eax, 56(%3)\n" - " movnti %%edx, 60(%3)\n" - " addl $-64, %0\n" - " addl $64, %4\n" - " addl $64, %3\n" - " cmpl $63, %0\n" - " ja 0b\n" - " sfence \n" - "5: movl %0, %%eax\n" - " shrl $2, %0\n" - " andl $3, %%eax\n" - " cld\n" - "6: rep; movsl\n" - " movl %%eax,%0\n" - "7: rep; movsb\n" - "8:\n" - ".section .fixup,\"ax\"\n" - "9: lea 0(%%eax,%0,4),%0\n" - "16: pushl %0\n" - " pushl %%eax\n" - " xorl %%eax,%%eax\n" - " rep; stosb\n" - " popl %%eax\n" - " popl %0\n" - " jmp 8b\n" - ".previous\n" - _ASM_EXTABLE(0b,16b) - _ASM_EXTABLE(1b,16b) - _ASM_EXTABLE(2b,16b) - _ASM_EXTABLE(21b,16b) - _ASM_EXTABLE(3b,16b) - _ASM_EXTABLE(31b,16b) - _ASM_EXTABLE(4b,16b) - _ASM_EXTABLE(41b,16b) - _ASM_EXTABLE(10b,16b) - _ASM_EXTABLE(51b,16b) - _ASM_EXTABLE(11b,16b) - _ASM_EXTABLE(61b,16b) - _ASM_EXTABLE(12b,16b) - _ASM_EXTABLE(71b,16b) - _ASM_EXTABLE(13b,16b) - _ASM_EXTABLE(81b,16b) - _ASM_EXTABLE(14b,16b) - _ASM_EXTABLE(91b,16b) - _ASM_EXTABLE(6b,9b) - _ASM_EXTABLE(7b,16b) - : "=&c"(size), "=&D" (d0), "=&S" (d1) - : "1"(to), "2"(from), "0"(size) - : "eax", "edx", "memory"); - return size; -} - static unsigned long __copy_user_intel_nocache(void *to, const void __user *from, unsigned long size) { @@ -486,12 +290,8 @@ static unsigned long __copy_user_intel_nocache(void *to, * Leave these declared but undefined. They should not be any references to * them */ -unsigned long __copy_user_zeroing_intel(void *to, const void __user *from, - unsigned long size); unsigned long __copy_user_intel(void __user *to, const void *from, unsigned long size); -unsigned long __copy_user_zeroing_intel_nocache(void *to, - const void __user *from, unsigned long size); #endif /* CONFIG_X86_INTEL_USERCOPY */ /* Generic arbitrary sized copy. */ @@ -528,47 +328,7 @@ do { \ : "memory"); \ } while (0) -#define __copy_user_zeroing(to, from, size) \ -do { \ - int __d0, __d1, __d2; \ - __asm__ __volatile__( \ - " cmp $7,%0\n" \ - " jbe 1f\n" \ - " movl %1,%0\n" \ - " negl %0\n" \ - " andl $7,%0\n" \ - " subl %0,%3\n" \ - "4: rep; movsb\n" \ - " movl %3,%0\n" \ - " shrl $2,%0\n" \ - " andl $3,%3\n" \ - " .align 2,0x90\n" \ - "0: rep; movsl\n" \ - " movl %3,%0\n" \ - "1: rep; movsb\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "5: addl %3,%0\n" \ - " jmp 6f\n" \ - "3: lea 0(%3,%0,4),%0\n" \ - "6: pushl %0\n" \ - " pushl %%eax\n" \ - " xorl %%eax,%%eax\n" \ - " rep; stosb\n" \ - " popl %%eax\n" \ - " popl %0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - _ASM_EXTABLE(4b,5b) \ - _ASM_EXTABLE(0b,3b) \ - _ASM_EXTABLE(1b,6b) \ - : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ - : "3"(size), "0"(size), "1"(to), "2"(from) \ - : "memory"); \ -} while (0) - -unsigned long __copy_to_user_ll(void __user *to, const void *from, - unsigned long n) +unsigned long __copy_user_ll(void *to, const void *from, unsigned long n) { stac(); if (movsl_is_ok(to, from, n)) @@ -578,51 +338,7 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, clac(); return n; } -EXPORT_SYMBOL(__copy_to_user_ll); - -unsigned long __copy_from_user_ll(void *to, const void __user *from, - unsigned long n) -{ - stac(); - if (movsl_is_ok(to, from, n)) - __copy_user_zeroing(to, from, n); - else - n = __copy_user_zeroing_intel(to, from, n); - clac(); - return n; -} -EXPORT_SYMBOL(__copy_from_user_ll); - -unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from, - unsigned long n) -{ - stac(); - if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); - else - n = __copy_user_intel((void __user *)to, - (const void *)from, n); - clac(); - return n; -} -EXPORT_SYMBOL(__copy_from_user_ll_nozero); - -unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from, - unsigned long n) -{ - stac(); -#ifdef CONFIG_X86_INTEL_USERCOPY - if (n > 64 && static_cpu_has(X86_FEATURE_XMM2)) - n = __copy_user_zeroing_intel_nocache(to, from, n); - else - __copy_user_zeroing(to, from, n); -#else - __copy_user_zeroing(to, from, n); -#endif - clac(); - return n; -} -EXPORT_SYMBOL(__copy_from_user_ll_nocache); +EXPORT_SYMBOL(__copy_user_ll); unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from, unsigned long n) diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c index 69873589c0ba..3b7c40a2e3e1 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c @@ -54,15 +54,6 @@ unsigned long clear_user(void __user *to, unsigned long n) } EXPORT_SYMBOL(clear_user); -unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len) -{ - if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { - return copy_user_generic((__force void *)to, (__force void *)from, len); - } - return len; -} -EXPORT_SYMBOL(copy_in_user); - /* * Try to copy last bytes and clear the rest if needed. * Since protection fault in copy_from/to_user is not a normal situation, @@ -80,9 +71,5 @@ copy_user_handle_tail(char *to, char *from, unsigned len) break; } clac(); - - /* If the destination is a kernel buffer, we always clear the end */ - if (!__addr_ok(to)) - memset(to, 0, len); return len; } diff --git a/arch/x86/mm/amdtopology.c b/arch/x86/mm/amdtopology.c index d1c7de095808..91f501b2da3b 100644 --- a/arch/x86/mm/amdtopology.c +++ b/arch/x86/mm/amdtopology.c @@ -19,7 +19,7 @@ #include <asm/types.h> #include <asm/mmzone.h> #include <asm/proto.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/pci-direct.h> #include <asm/numa.h> #include <asm/mpspec.h> diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index 58b5bee7ea27..bce6990b1d81 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c @@ -110,7 +110,8 @@ static struct addr_marker address_markers[] = { #define PTE_LEVEL_MULT (PAGE_SIZE) #define PMD_LEVEL_MULT (PTRS_PER_PTE * PTE_LEVEL_MULT) #define PUD_LEVEL_MULT (PTRS_PER_PMD * PMD_LEVEL_MULT) -#define PGD_LEVEL_MULT (PTRS_PER_PUD * PUD_LEVEL_MULT) +#define P4D_LEVEL_MULT (PTRS_PER_PUD * PUD_LEVEL_MULT) +#define PGD_LEVEL_MULT (PTRS_PER_P4D * P4D_LEVEL_MULT) #define pt_dump_seq_printf(m, to_dmesg, fmt, args...) \ ({ \ @@ -286,14 +287,13 @@ static void note_page(struct seq_file *m, struct pg_state *st, } } -static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr, - unsigned long P) +static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr, unsigned long P) { int i; pte_t *start; pgprotval_t prot; - start = (pte_t *) pmd_page_vaddr(addr); + start = (pte_t *)pmd_page_vaddr(addr); for (i = 0; i < PTRS_PER_PTE; i++) { prot = pte_flags(*start); st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); @@ -304,14 +304,13 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr, #if PTRS_PER_PMD > 1 -static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr, - unsigned long P) +static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr, unsigned long P) { int i; pmd_t *start; pgprotval_t prot; - start = (pmd_t *) pud_page_vaddr(addr); + start = (pmd_t *)pud_page_vaddr(addr); for (i = 0; i < PTRS_PER_PMD; i++) { st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT); if (!pmd_none(*start)) { @@ -347,15 +346,14 @@ static bool pud_already_checked(pud_t *prev_pud, pud_t *pud, bool checkwx) return checkwx && prev_pud && (pud_val(*prev_pud) == pud_val(*pud)); } -static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr, - unsigned long P) +static void walk_pud_level(struct seq_file *m, struct pg_state *st, p4d_t addr, unsigned long P) { int i; pud_t *start; pgprotval_t prot; pud_t *prev_pud = NULL; - start = (pud_t *) pgd_page_vaddr(addr); + start = (pud_t *)p4d_page_vaddr(addr); for (i = 0; i < PTRS_PER_PUD; i++) { st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT); @@ -377,9 +375,42 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr, } #else -#define walk_pud_level(m,s,a,p) walk_pmd_level(m,s,__pud(pgd_val(a)),p) -#define pgd_large(a) pud_large(__pud(pgd_val(a))) -#define pgd_none(a) pud_none(__pud(pgd_val(a))) +#define walk_pud_level(m,s,a,p) walk_pmd_level(m,s,__pud(p4d_val(a)),p) +#define p4d_large(a) pud_large(__pud(p4d_val(a))) +#define p4d_none(a) pud_none(__pud(p4d_val(a))) +#endif + +#if PTRS_PER_P4D > 1 + +static void walk_p4d_level(struct seq_file *m, struct pg_state *st, pgd_t addr, unsigned long P) +{ + int i; + p4d_t *start; + pgprotval_t prot; + + start = (p4d_t *)pgd_page_vaddr(addr); + + for (i = 0; i < PTRS_PER_P4D; i++) { + st->current_address = normalize_addr(P + i * P4D_LEVEL_MULT); + if (!p4d_none(*start)) { + if (p4d_large(*start) || !p4d_present(*start)) { + prot = p4d_flags(*start); + note_page(m, st, __pgprot(prot), 2); + } else { + walk_pud_level(m, st, *start, + P + i * P4D_LEVEL_MULT); + } + } else + note_page(m, st, __pgprot(0), 2); + + start++; + } +} + +#else +#define walk_p4d_level(m,s,a,p) walk_pud_level(m,s,__p4d(pgd_val(a)),p) +#define pgd_large(a) p4d_large(__p4d(pgd_val(a))) +#define pgd_none(a) p4d_none(__p4d(pgd_val(a))) #endif static inline bool is_hypervisor_range(int idx) @@ -424,7 +455,7 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, prot = pgd_flags(*start); note_page(m, &st, __pgprot(prot), 1); } else { - walk_pud_level(m, &st, *start, + walk_p4d_level(m, &st, *start, i * PGD_LEVEL_MULT); } } else diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 428e31763cb9..8ad91a01cbc8 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -253,6 +253,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) { unsigned index = pgd_index(address); pgd_t *pgd_k; + p4d_t *p4d, *p4d_k; pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; @@ -265,10 +266,15 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) /* * set_pgd(pgd, *pgd_k); here would be useless on PAE * and redundant with the set_pmd() on non-PAE. As would - * set_pud. + * set_p4d/set_pud. */ - pud = pud_offset(pgd, address); - pud_k = pud_offset(pgd_k, address); + p4d = p4d_offset(pgd, address); + p4d_k = p4d_offset(pgd_k, address); + if (!p4d_present(*p4d_k)) + return NULL; + + pud = pud_offset(p4d, address); + pud_k = pud_offset(p4d_k, address); if (!pud_present(*pud_k)) return NULL; @@ -384,6 +390,8 @@ static void dump_pagetable(unsigned long address) { pgd_t *base = __va(read_cr3()); pgd_t *pgd = &base[pgd_index(address)]; + p4d_t *p4d; + pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -392,7 +400,9 @@ static void dump_pagetable(unsigned long address) if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd)) goto out; #endif - pmd = pmd_offset(pud_offset(pgd, address), address); + p4d = p4d_offset(pgd, address); + pud = pud_offset(p4d, address); + pmd = pmd_offset(pud, address); printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd)); /* @@ -425,6 +435,7 @@ void vmalloc_sync_all(void) static noinline int vmalloc_fault(unsigned long address) { pgd_t *pgd, *pgd_ref; + p4d_t *p4d, *p4d_ref; pud_t *pud, *pud_ref; pmd_t *pmd, *pmd_ref; pte_t *pte, *pte_ref; @@ -448,17 +459,37 @@ static noinline int vmalloc_fault(unsigned long address) if (pgd_none(*pgd)) { set_pgd(pgd, *pgd_ref); arch_flush_lazy_mmu_mode(); - } else { + } else if (CONFIG_PGTABLE_LEVELS > 4) { + /* + * With folded p4d, pgd_none() is always false, so the pgd may + * point to an empty page table entry and pgd_page_vaddr() + * will return garbage. + * + * We will do the correct sanity check on the p4d level. + */ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); } + /* With 4-level paging, copying happens on the p4d level. */ + p4d = p4d_offset(pgd, address); + p4d_ref = p4d_offset(pgd_ref, address); + if (p4d_none(*p4d_ref)) + return -1; + + if (p4d_none(*p4d)) { + set_p4d(p4d, *p4d_ref); + arch_flush_lazy_mmu_mode(); + } else { + BUG_ON(p4d_pfn(*p4d) != p4d_pfn(*p4d_ref)); + } + /* * Below here mismatches are bugs because these lower tables * are shared: */ - pud = pud_offset(pgd, address); - pud_ref = pud_offset(pgd_ref, address); + pud = pud_offset(p4d, address); + pud_ref = pud_offset(p4d_ref, address); if (pud_none(*pud_ref)) return -1; @@ -526,6 +557,7 @@ static void dump_pagetable(unsigned long address) { pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK); pgd_t *pgd = base + pgd_index(address); + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -538,7 +570,15 @@ static void dump_pagetable(unsigned long address) if (!pgd_present(*pgd)) goto out; - pud = pud_offset(pgd, address); + p4d = p4d_offset(pgd, address); + if (bad_address(p4d)) + goto bad; + + printk("P4D %lx ", p4d_val(*p4d)); + if (!p4d_present(*p4d) || p4d_large(*p4d)) + goto out; + + pud = pud_offset(p4d, address); if (bad_address(pud)) goto bad; @@ -1082,6 +1122,7 @@ static noinline int spurious_fault(unsigned long error_code, unsigned long address) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -1104,7 +1145,14 @@ spurious_fault(unsigned long error_code, unsigned long address) if (!pgd_present(*pgd)) return 0; - pud = pud_offset(pgd, address); + p4d = p4d_offset(pgd, address); + if (!p4d_present(*p4d)) + return 0; + + if (p4d_large(*p4d)) + return spurious_fault_check(error_code, (pte_t *) p4d); + + pud = pud_offset(p4d, address); if (!pud_present(*pud)) return 0; diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index 99c7805a9693..456dfdfd2249 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -76,9 +76,9 @@ static void undo_dev_pagemap(int *nr, int nr_start, struct page **pages) } /* - * 'pteval' can come from a pte, pmd or pud. We only check + * 'pteval' can come from a pte, pmd, pud or p4d. We only check * _PAGE_PRESENT, _PAGE_USER, and _PAGE_RW in here which are the - * same value on all 3 types. + * same value on all 4 types. */ static inline int pte_allows_gup(unsigned long pteval, int write) { @@ -106,32 +106,35 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, int write, struct page **pages, int *nr) { struct dev_pagemap *pgmap = NULL; - int nr_start = *nr; - pte_t *ptep; + int nr_start = *nr, ret = 0; + pte_t *ptep, *ptem; - ptep = pte_offset_map(&pmd, addr); + /* + * Keep the original mapped PTE value (ptem) around since we + * might increment ptep off the end of the page when finishing + * our loop iteration. + */ + ptem = ptep = pte_offset_map(&pmd, addr); do { pte_t pte = gup_get_pte(ptep); struct page *page; /* Similar to the PMD case, NUMA hinting must take slow path */ - if (pte_protnone(pte)) { - pte_unmap(ptep); - return 0; - } + if (pte_protnone(pte)) + break; + + if (!pte_allows_gup(pte_val(pte), write)) + break; if (pte_devmap(pte)) { pgmap = get_dev_pagemap(pte_pfn(pte), pgmap); if (unlikely(!pgmap)) { undo_dev_pagemap(nr, nr_start, pages); - pte_unmap(ptep); - return 0; + break; } - } else if (!pte_allows_gup(pte_val(pte), write) || - pte_special(pte)) { - pte_unmap(ptep); - return 0; - } + } else if (pte_special(pte)) + break; + VM_BUG_ON(!pfn_valid(pte_pfn(pte))); page = pte_page(pte); get_page(page); @@ -141,9 +144,11 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, (*nr)++; } while (ptep++, addr += PAGE_SIZE, addr != end); - pte_unmap(ptep - 1); + if (addr == end) + ret = 1; + pte_unmap(ptem); - return 1; + return ret; } static inline void get_head_page_multiple(struct page *page, int nr) @@ -290,13 +295,13 @@ static noinline int gup_huge_pud(pud_t pud, unsigned long addr, return 1; } -static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, +static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end, int write, struct page **pages, int *nr) { unsigned long next; pud_t *pudp; - pudp = pud_offset(&pgd, addr); + pudp = pud_offset(&p4d, addr); do { pud_t pud = *pudp; @@ -315,6 +320,27 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, return 1; } +static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end, + int write, struct page **pages, int *nr) +{ + unsigned long next; + p4d_t *p4dp; + + p4dp = p4d_offset(&pgd, addr); + do { + p4d_t p4d = *p4dp; + + next = p4d_addr_end(addr, end); + if (p4d_none(p4d)) + return 0; + BUILD_BUG_ON(p4d_large(p4d)); + if (!gup_pud_range(p4d, addr, next, write, pages, nr)) + return 0; + } while (p4dp++, addr = next, addr != end); + + return 1; +} + /* * Like get_user_pages_fast() except its IRQ-safe in that it won't fall * back to the regular GUP. @@ -363,7 +389,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, next = pgd_addr_end(addr, end); if (pgd_none(pgd)) break; - if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) + if (!gup_p4d_range(pgd, addr, next, write, pages, &nr)) break; } while (pgdp++, addr = next, addr != end); local_irq_restore(flags); @@ -435,7 +461,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, next = pgd_addr_end(addr, end); if (pgd_none(pgd)) goto slow; - if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) + if (!gup_p4d_range(pgd, addr, next, write, pages, &nr)) goto slow; } while (pgdp++, addr = next, addr != end); local_irq_enable(); diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index c5066a260803..302f43fd9c28 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -12,10 +12,12 @@ #include <linux/pagemap.h> #include <linux/err.h> #include <linux/sysctl.h> +#include <linux/compat.h> #include <asm/mman.h> #include <asm/tlb.h> #include <asm/tlbflush.h> #include <asm/pgalloc.h> +#include <asm/elf.h> #if 0 /* This is just for testing */ struct page * @@ -82,8 +84,9 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, info.flags = 0; info.length = len; - info.low_limit = current->mm->mmap_legacy_base; - info.high_limit = TASK_SIZE; + info.low_limit = get_mmap_base(1); + info.high_limit = in_compat_syscall() ? + tasksize_32bit() : tasksize_64bit(); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; return vm_unmapped_area(&info); @@ -100,7 +103,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; info.low_limit = PAGE_SIZE; - info.high_limit = current->mm->mmap_base; + info.high_limit = get_mmap_base(0); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; addr = vm_unmapped_area(&info); diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c index 4473cb4f8b90..04210a29dd60 100644 --- a/arch/x86/mm/ident_map.c +++ b/arch/x86/mm/ident_map.c @@ -45,6 +45,34 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, return 0; } +static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page, + unsigned long addr, unsigned long end) +{ + unsigned long next; + + for (; addr < end; addr = next) { + p4d_t *p4d = p4d_page + p4d_index(addr); + pud_t *pud; + + next = (addr & P4D_MASK) + P4D_SIZE; + if (next > end) + next = end; + + if (p4d_present(*p4d)) { + pud = pud_offset(p4d, 0); + ident_pud_init(info, pud, addr, next); + continue; + } + pud = (pud_t *)info->alloc_pgt_page(info->context); + if (!pud) + return -ENOMEM; + ident_pud_init(info, pud, addr, next); + set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE)); + } + + return 0; +} + int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page, unsigned long pstart, unsigned long pend) { @@ -55,27 +83,36 @@ int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page, for (; addr < end; addr = next) { pgd_t *pgd = pgd_page + pgd_index(addr); - pud_t *pud; + p4d_t *p4d; next = (addr & PGDIR_MASK) + PGDIR_SIZE; if (next > end) next = end; if (pgd_present(*pgd)) { - pud = pud_offset(pgd, 0); - result = ident_pud_init(info, pud, addr, next); + p4d = p4d_offset(pgd, 0); + result = ident_p4d_init(info, p4d, addr, next); if (result) return result; continue; } - pud = (pud_t *)info->alloc_pgt_page(info->context); - if (!pud) + p4d = (p4d_t *)info->alloc_pgt_page(info->context); + if (!p4d) return -ENOMEM; - result = ident_pud_init(info, pud, addr, next); + result = ident_p4d_init(info, p4d, addr, next); if (result) return result; - set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE)); + if (IS_ENABLED(CONFIG_X86_5LEVEL)) { + set_pgd(pgd, __pgd(__pa(p4d) | _KERNPG_TABLE)); + } else { + /* + * With p4d folded, pgd is equal to p4d. + * The pgd entry has to point to the pud page table in this case. + */ + pud_t *pud = pud_offset(p4d, 0); + set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE)); + } } return 0; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 22af912d66d2..138bad2fb6bc 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -6,7 +6,7 @@ #include <linux/bootmem.h> /* for max_low_pfn */ #include <asm/cacheflush.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/init.h> #include <asm/page.h> #include <asm/page_types.h> @@ -373,14 +373,14 @@ static int __meminit split_mem_range(struct map_range *mr, int nr_range, return nr_range; } -struct range pfn_mapped[E820_X_MAX]; +struct range pfn_mapped[E820_MAX_ENTRIES]; int nr_pfn_mapped; static void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn) { - nr_pfn_mapped = add_range_with_merge(pfn_mapped, E820_X_MAX, + nr_pfn_mapped = add_range_with_merge(pfn_mapped, E820_MAX_ENTRIES, nr_pfn_mapped, start_pfn, end_pfn); - nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_X_MAX); + nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_MAX_ENTRIES); max_pfn_mapped = max(max_pfn_mapped, end_pfn); @@ -430,7 +430,7 @@ unsigned long __ref init_memory_mapping(unsigned long start, /* * We need to iterate through the E820 memory map and create direct mappings - * for only E820_RAM and E820_KERN_RESERVED regions. We cannot simply + * for only E820_TYPE_RAM and E820_KERN_RESERVED regions. We cannot simply * create direct mappings for all pfns from [0 to max_low_pfn) and * [4GB to max_pfn) because of possible memory holes in high addresses * that cannot be marked as UC by fixed/variable range MTRRs. @@ -643,21 +643,40 @@ void __init init_mem_mapping(void) * devmem_is_allowed() checks to see if /dev/mem access to a certain address * is valid. The argument is a physical page number. * - * - * On x86, access has to be given to the first megabyte of ram because that area - * contains BIOS code and data regions used by X and dosemu and similar apps. - * Access has to be given to non-kernel-ram areas as well, these contain the PCI - * mmio resources as well as potential bios/acpi data regions. + * On x86, access has to be given to the first megabyte of RAM because that + * area traditionally contains BIOS code and data regions used by X, dosemu, + * and similar apps. Since they map the entire memory range, the whole range + * must be allowed (for mapping), but any areas that would otherwise be + * disallowed are flagged as being "zero filled" instead of rejected. + * Access has to be given to non-kernel-ram areas as well, these contain the + * PCI mmio resources as well as potential bios/acpi data regions. */ int devmem_is_allowed(unsigned long pagenr) { - if (pagenr < 256) - return 1; - if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) + if (page_is_ram(pagenr)) { + /* + * For disallowed memory regions in the low 1MB range, + * request that the page be shown as all zeros. + */ + if (pagenr < 256) + return 2; + return 0; - if (!page_is_ram(pagenr)) - return 1; - return 0; + } + + /* + * This must follow RAM test, since System RAM is considered a + * restricted resource under CONFIG_STRICT_IOMEM. + */ + if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) { + /* Low 1MB bypasses iomem restrictions. */ + if (pagenr < 256) + return 1; + + return 0; + } + + return 1; } void free_init_pages(char *what, unsigned long begin, unsigned long end) @@ -701,7 +720,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) void __ref free_initmem(void) { - e820_reallocate_tables(); + e820__reallocate_tables(); free_init_pages("unused kernel", (unsigned long)(&__init_begin), @@ -724,6 +743,53 @@ void __init free_initrd_mem(unsigned long start, unsigned long end) } #endif +/* + * Calculate the precise size of the DMA zone (first 16 MB of RAM), + * and pass it to the MM layer - to help it set zone watermarks more + * accurately. + * + * Done on 64-bit systems only for the time being, although 32-bit systems + * might benefit from this as well. + */ +void __init memblock_find_dma_reserve(void) +{ +#ifdef CONFIG_X86_64 + u64 nr_pages = 0, nr_free_pages = 0; + unsigned long start_pfn, end_pfn; + phys_addr_t start_addr, end_addr; + int i; + u64 u; + + /* + * Iterate over all memory ranges (free and reserved ones alike), + * to calculate the total number of pages in the first 16 MB of RAM: + */ + nr_pages = 0; + for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) { + start_pfn = min(start_pfn, MAX_DMA_PFN); + end_pfn = min(end_pfn, MAX_DMA_PFN); + + nr_pages += end_pfn - start_pfn; + } + + /* + * Iterate over free memory ranges to calculate the number of free + * pages in the DMA zone, while not counting potential partial + * pages at the beginning or the end of the range: + */ + nr_free_pages = 0; + for_each_free_mem_range(u, NUMA_NO_NODE, MEMBLOCK_NONE, &start_addr, &end_addr, NULL) { + start_pfn = min_t(unsigned long, PFN_UP(start_addr), MAX_DMA_PFN); + end_pfn = min_t(unsigned long, PFN_DOWN(end_addr), MAX_DMA_PFN); + + if (start_pfn < end_pfn) + nr_free_pages += end_pfn - start_pfn; + } + + set_dma_reserve(nr_pages - nr_free_pages); +#endif +} + void __init zone_sizes_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 2b4b53e6793f..f34d275ee201 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -38,7 +38,7 @@ #include <asm/pgtable.h> #include <asm/dma.h> #include <asm/fixmap.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/apic.h> #include <asm/bugs.h> #include <asm/tlb.h> @@ -56,8 +56,6 @@ unsigned long highstart_pfn, highend_pfn; -static noinline int do_test_wp_bit(void); - bool __read_mostly __vmalloc_start_set = false; /* @@ -67,6 +65,7 @@ bool __read_mostly __vmalloc_start_set = false; */ static pmd_t * __init one_md_table_init(pgd_t *pgd) { + p4d_t *p4d; pud_t *pud; pmd_t *pmd_table; @@ -75,13 +74,15 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd) pmd_table = (pmd_t *)alloc_low_page(); paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT); set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); - pud = pud_offset(pgd, 0); + p4d = p4d_offset(pgd, 0); + pud = pud_offset(p4d, 0); BUG_ON(pmd_table != pmd_offset(pud, 0)); return pmd_table; } #endif - pud = pud_offset(pgd, 0); + p4d = p4d_offset(pgd, 0); + pud = pud_offset(p4d, 0); pmd_table = pmd_offset(pud, 0); return pmd_table; @@ -390,8 +391,11 @@ pte_t *kmap_pte; static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr) { - return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), - vaddr), vaddr), vaddr); + pgd_t *pgd = pgd_offset_k(vaddr); + p4d_t *p4d = p4d_offset(pgd, vaddr); + pud_t *pud = pud_offset(p4d, vaddr); + pmd_t *pmd = pmd_offset(pud, vaddr); + return pte_offset_kernel(pmd, vaddr); } static void __init kmap_init(void) @@ -410,6 +414,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) { unsigned long vaddr; pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -418,7 +423,8 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); pgd = swapper_pg_dir + pgd_index(vaddr); - pud = pud_offset(pgd, vaddr); + p4d = p4d_offset(pgd, vaddr); + pud = pud_offset(p4d, vaddr); pmd = pmd_offset(pud, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; @@ -450,6 +456,7 @@ void __init native_pagetable_init(void) { unsigned long pfn, va; pgd_t *pgd, *base = swapper_pg_dir; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -469,7 +476,8 @@ void __init native_pagetable_init(void) if (!pgd_present(*pgd)) break; - pud = pud_offset(pgd, va); + p4d = p4d_offset(pgd, va); + pud = pud_offset(p4d, va); pmd = pmd_offset(pud, va); if (!pmd_present(*pmd)) break; @@ -716,20 +724,20 @@ void __init paging_init(void) */ static void __init test_wp_bit(void) { - printk(KERN_INFO - "Checking if this processor honours the WP bit even in supervisor mode..."); + char z = 0; + + printk(KERN_INFO "Checking if this processor honours the WP bit even in supervisor mode..."); - /* Any page-aligned address will do, the test is non-destructive */ - __set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_KERNEL_RO); - boot_cpu_data.wp_works_ok = do_test_wp_bit(); - clear_fixmap(FIX_WP_TEST); + __set_fixmap(FIX_WP_TEST, __pa_symbol(empty_zero_page), PAGE_KERNEL_RO); - if (!boot_cpu_data.wp_works_ok) { - printk(KERN_CONT "No.\n"); - panic("Linux doesn't support CPUs with broken WP."); - } else { + if (probe_kernel_write((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) { + clear_fixmap(FIX_WP_TEST); printk(KERN_CONT "Ok.\n"); + return; } + + printk(KERN_CONT "No.\n"); + panic("Linux doesn't support CPUs with broken WP."); } void __init mem_init(void) @@ -811,8 +819,7 @@ void __init mem_init(void) BUG_ON(VMALLOC_START >= VMALLOC_END); BUG_ON((unsigned long)high_memory > VMALLOC_START); - if (boot_cpu_data.wp_works_ok < 0) - test_wp_bit(); + test_wp_bit(); } #ifdef CONFIG_MEMORY_HOTPLUG @@ -840,30 +847,6 @@ int arch_remove_memory(u64 start, u64 size) #endif #endif -/* - * This function cannot be __init, since exceptions don't work in that - * section. Put this after the callers, so that it cannot be inlined. - */ -static noinline int do_test_wp_bit(void) -{ - char tmp_reg; - int flag; - - __asm__ __volatile__( - " movb %0, %1 \n" - "1: movb %1, %0 \n" - " xorl %2, %2 \n" - "2: \n" - _ASM_EXTABLE(1b,2b) - :"=m" (*(char *)fix_to_virt(FIX_WP_TEST)), - "=q" (tmp_reg), - "=r" (flag) - :"2" (1) - :"memory"); - - return flag; -} - int kernel_set_to_readonly __read_mostly; void set_kernel_text_rw(void) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 15173d37f399..745e5e183169 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -41,7 +41,7 @@ #include <asm/pgalloc.h> #include <asm/dma.h> #include <asm/fixmap.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/apic.h> #include <asm/tlb.h> #include <asm/mmu_context.h> @@ -97,28 +97,38 @@ void sync_global_pgds(unsigned long start, unsigned long end) unsigned long address; for (address = start; address <= end; address += PGDIR_SIZE) { - const pgd_t *pgd_ref = pgd_offset_k(address); + pgd_t *pgd_ref = pgd_offset_k(address); + const p4d_t *p4d_ref; struct page *page; - if (pgd_none(*pgd_ref)) + /* + * With folded p4d, pgd_none() is always false, we need to + * handle synchonization on p4d level. + */ + BUILD_BUG_ON(pgd_none(*pgd_ref)); + p4d_ref = p4d_offset(pgd_ref, address); + + if (p4d_none(*p4d_ref)) continue; spin_lock(&pgd_lock); list_for_each_entry(page, &pgd_list, lru) { pgd_t *pgd; + p4d_t *p4d; spinlock_t *pgt_lock; pgd = (pgd_t *)page_address(page) + pgd_index(address); + p4d = p4d_offset(pgd, address); /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); - if (!pgd_none(*pgd_ref) && !pgd_none(*pgd)) - BUG_ON(pgd_page_vaddr(*pgd) - != pgd_page_vaddr(*pgd_ref)); + if (!p4d_none(*p4d_ref) && !p4d_none(*p4d)) + BUG_ON(p4d_page_vaddr(*p4d) + != p4d_page_vaddr(*p4d_ref)); - if (pgd_none(*pgd)) - set_pgd(pgd, *pgd_ref); + if (p4d_none(*p4d)) + set_p4d(p4d, *p4d_ref); spin_unlock(pgt_lock); } @@ -149,16 +159,28 @@ static __ref void *spp_getpage(void) return ptr; } -static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) +static p4d_t *fill_p4d(pgd_t *pgd, unsigned long vaddr) { if (pgd_none(*pgd)) { - pud_t *pud = (pud_t *)spp_getpage(); - pgd_populate(&init_mm, pgd, pud); - if (pud != pud_offset(pgd, 0)) + p4d_t *p4d = (p4d_t *)spp_getpage(); + pgd_populate(&init_mm, pgd, p4d); + if (p4d != p4d_offset(pgd, 0)) printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n", - pud, pud_offset(pgd, 0)); + p4d, p4d_offset(pgd, 0)); + } + return p4d_offset(pgd, vaddr); +} + +static pud_t *fill_pud(p4d_t *p4d, unsigned long vaddr) +{ + if (p4d_none(*p4d)) { + pud_t *pud = (pud_t *)spp_getpage(); + p4d_populate(&init_mm, p4d, pud); + if (pud != pud_offset(p4d, 0)) + printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", + pud, pud_offset(p4d, 0)); } - return pud_offset(pgd, vaddr); + return pud_offset(p4d, vaddr); } static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) @@ -167,7 +189,7 @@ static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) pmd_t *pmd = (pmd_t *) spp_getpage(); pud_populate(&init_mm, pud, pmd); if (pmd != pmd_offset(pud, 0)) - printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", + printk(KERN_ERR "PAGETABLE BUG #02! %p <-> %p\n", pmd, pmd_offset(pud, 0)); } return pmd_offset(pud, vaddr); @@ -179,20 +201,15 @@ static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr) pte_t *pte = (pte_t *) spp_getpage(); pmd_populate_kernel(&init_mm, pmd, pte); if (pte != pte_offset_kernel(pmd, 0)) - printk(KERN_ERR "PAGETABLE BUG #02!\n"); + printk(KERN_ERR "PAGETABLE BUG #03!\n"); } return pte_offset_kernel(pmd, vaddr); } -void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) +static void __set_pte_vaddr(pud_t *pud, unsigned long vaddr, pte_t new_pte) { - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - - pud = pud_page + pud_index(vaddr); - pmd = fill_pmd(pud, vaddr); - pte = fill_pte(pmd, vaddr); + pmd_t *pmd = fill_pmd(pud, vaddr); + pte_t *pte = fill_pte(pmd, vaddr); set_pte(pte, new_pte); @@ -203,10 +220,25 @@ void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) __flush_tlb_one(vaddr); } +void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pte_t new_pte) +{ + p4d_t *p4d = p4d_page + p4d_index(vaddr); + pud_t *pud = fill_pud(p4d, vaddr); + + __set_pte_vaddr(pud, vaddr, new_pte); +} + +void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) +{ + pud_t *pud = pud_page + pud_index(vaddr); + + __set_pte_vaddr(pud, vaddr, new_pte); +} + void set_pte_vaddr(unsigned long vaddr, pte_t pteval) { pgd_t *pgd; - pud_t *pud_page; + p4d_t *p4d_page; pr_debug("set_pte_vaddr %lx to %lx\n", vaddr, native_pte_val(pteval)); @@ -216,17 +248,20 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pteval) "PGD FIXMAP MISSING, it should be setup in head.S!\n"); return; } - pud_page = (pud_t*)pgd_page_vaddr(*pgd); - set_pte_vaddr_pud(pud_page, vaddr, pteval); + + p4d_page = p4d_offset(pgd, 0); + set_pte_vaddr_p4d(p4d_page, vaddr, pteval); } pmd_t * __init populate_extra_pmd(unsigned long vaddr) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pgd = pgd_offset_k(vaddr); - pud = fill_pud(pgd, vaddr); + p4d = fill_p4d(pgd, vaddr); + pud = fill_pud(p4d, vaddr); return fill_pmd(pud, vaddr); } @@ -245,6 +280,7 @@ static void __init __init_extra_mapping(unsigned long phys, unsigned long size, enum page_cache_mode cache) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pgprot_t prot; @@ -255,11 +291,17 @@ static void __init __init_extra_mapping(unsigned long phys, unsigned long size, for (; size; phys += PMD_SIZE, size -= PMD_SIZE) { pgd = pgd_offset_k((unsigned long)__va(phys)); if (pgd_none(*pgd)) { + p4d = (p4d_t *) spp_getpage(); + set_pgd(pgd, __pgd(__pa(p4d) | _KERNPG_TABLE | + _PAGE_USER)); + } + p4d = p4d_offset(pgd, (unsigned long)__va(phys)); + if (p4d_none(*p4d)) { pud = (pud_t *) spp_getpage(); - set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE | + set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE | _PAGE_USER)); } - pud = pud_offset(pgd, (unsigned long)__va(phys)); + pud = pud_offset(p4d, (unsigned long)__va(phys)); if (pud_none(*pud)) { pmd = (pmd_t *) spp_getpage(); set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | @@ -337,10 +379,10 @@ phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end, paddr_next = (paddr & PAGE_MASK) + PAGE_SIZE; if (paddr >= paddr_end) { if (!after_bootmem && - !e820_any_mapped(paddr & PAGE_MASK, paddr_next, - E820_RAM) && - !e820_any_mapped(paddr & PAGE_MASK, paddr_next, - E820_RESERVED_KERN)) + !e820__mapped_any(paddr & PAGE_MASK, paddr_next, + E820_TYPE_RAM) && + !e820__mapped_any(paddr & PAGE_MASK, paddr_next, + E820_TYPE_RESERVED_KERN)) set_pte(pte, __pte(0)); continue; } @@ -392,10 +434,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end, paddr_next = (paddr & PMD_MASK) + PMD_SIZE; if (paddr >= paddr_end) { if (!after_bootmem && - !e820_any_mapped(paddr & PMD_MASK, paddr_next, - E820_RAM) && - !e820_any_mapped(paddr & PMD_MASK, paddr_next, - E820_RESERVED_KERN)) + !e820__mapped_any(paddr & PMD_MASK, paddr_next, + E820_TYPE_RAM) && + !e820__mapped_any(paddr & PMD_MASK, paddr_next, + E820_TYPE_RESERVED_KERN)) set_pmd(pmd, __pmd(0)); continue; } @@ -478,10 +520,10 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end, if (paddr >= paddr_end) { if (!after_bootmem && - !e820_any_mapped(paddr & PUD_MASK, paddr_next, - E820_RAM) && - !e820_any_mapped(paddr & PUD_MASK, paddr_next, - E820_RESERVED_KERN)) + !e820__mapped_any(paddr & PUD_MASK, paddr_next, + E820_TYPE_RAM) && + !e820__mapped_any(paddr & PUD_MASK, paddr_next, + E820_TYPE_RESERVED_KERN)) set_pud(pud, __pud(0)); continue; } @@ -563,12 +605,15 @@ kernel_physical_mapping_init(unsigned long paddr_start, for (; vaddr < vaddr_end; vaddr = vaddr_next) { pgd_t *pgd = pgd_offset_k(vaddr); + p4d_t *p4d; pud_t *pud; vaddr_next = (vaddr & PGDIR_MASK) + PGDIR_SIZE; - if (pgd_val(*pgd)) { - pud = (pud_t *)pgd_page_vaddr(*pgd); + BUILD_BUG_ON(pgd_none(*pgd)); + p4d = p4d_offset(pgd, vaddr); + if (p4d_val(*p4d)) { + pud = (pud_t *)p4d_page_vaddr(*p4d); paddr_last = phys_pud_init(pud, __pa(vaddr), __pa(vaddr_end), page_size_mask); @@ -580,7 +625,7 @@ kernel_physical_mapping_init(unsigned long paddr_start, page_size_mask); spin_lock(&init_mm.page_table_lock); - pgd_populate(&init_mm, pgd, pud); + p4d_populate(&init_mm, p4d, pud); spin_unlock(&init_mm.page_table_lock); pgd_changed = true; } @@ -726,6 +771,24 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud) spin_unlock(&init_mm.page_table_lock); } +static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d) +{ + pud_t *pud; + int i; + + for (i = 0; i < PTRS_PER_PUD; i++) { + pud = pud_start + i; + if (!pud_none(*pud)) + return; + } + + /* free a pud talbe */ + free_pagetable(p4d_page(*p4d), 0); + spin_lock(&init_mm.page_table_lock); + p4d_clear(p4d); + spin_unlock(&init_mm.page_table_lock); +} + static void __meminit remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end, bool direct) @@ -899,7 +962,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end, continue; } - pmd_base = (pmd_t *)pud_page_vaddr(*pud); + pmd_base = pmd_offset(pud, 0); remove_pmd_table(pmd_base, addr, next, direct); free_pmd_table(pmd_base, pud); } @@ -908,6 +971,32 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end, update_page_count(PG_LEVEL_1G, -pages); } +static void __meminit +remove_p4d_table(p4d_t *p4d_start, unsigned long addr, unsigned long end, + bool direct) +{ + unsigned long next, pages = 0; + pud_t *pud_base; + p4d_t *p4d; + + p4d = p4d_start + p4d_index(addr); + for (; addr < end; addr = next, p4d++) { + next = p4d_addr_end(addr, end); + + if (!p4d_present(*p4d)) + continue; + + BUILD_BUG_ON(p4d_large(*p4d)); + + pud_base = pud_offset(p4d, 0); + remove_pud_table(pud_base, addr, next, direct); + free_pud_table(pud_base, p4d); + } + + if (direct) + update_page_count(PG_LEVEL_512G, -pages); +} + /* start and end are both virtual address. */ static void __meminit remove_pagetable(unsigned long start, unsigned long end, bool direct) @@ -915,7 +1004,7 @@ remove_pagetable(unsigned long start, unsigned long end, bool direct) unsigned long next; unsigned long addr; pgd_t *pgd; - pud_t *pud; + p4d_t *p4d; for (addr = start; addr < end; addr = next) { next = pgd_addr_end(addr, end); @@ -924,8 +1013,8 @@ remove_pagetable(unsigned long start, unsigned long end, bool direct) if (!pgd_present(*pgd)) continue; - pud = (pud_t *)pgd_page_vaddr(*pgd); - remove_pud_table(pud, addr, next, direct); + p4d = p4d_offset(pgd, 0); + remove_p4d_table(p4d, addr, next, direct); } flush_tlb_all(); @@ -1090,6 +1179,7 @@ int kern_addr_valid(unsigned long addr) { unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT; pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -1101,7 +1191,11 @@ int kern_addr_valid(unsigned long addr) if (pgd_none(*pgd)) return 0; - pud = pud_offset(pgd, addr); + p4d = p4d_offset(pgd, addr); + if (p4d_none(*p4d)) + return 0; + + pud = pud_offset(p4d, addr); if (pud_none(*pud)) return 0; @@ -1158,6 +1252,7 @@ static int __meminit vmemmap_populate_hugepages(unsigned long start, unsigned long addr; unsigned long next; pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; @@ -1168,7 +1263,11 @@ static int __meminit vmemmap_populate_hugepages(unsigned long start, if (!pgd) return -ENOMEM; - pud = vmemmap_pud_populate(pgd, addr, node); + p4d = vmemmap_p4d_populate(pgd, addr, node); + if (!p4d) + return -ENOMEM; + + pud = vmemmap_pud_populate(p4d, addr, node); if (!pud) return -ENOMEM; @@ -1236,6 +1335,7 @@ void register_page_bootmem_memmap(unsigned long section_nr, unsigned long end = (unsigned long)(start_page + size); unsigned long next; pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; unsigned int nr_pages; @@ -1251,7 +1351,14 @@ void register_page_bootmem_memmap(unsigned long section_nr, } get_page_bootmem(section_nr, pgd_page(*pgd), MIX_SECTION_INFO); - pud = pud_offset(pgd, addr); + p4d = p4d_offset(pgd, addr); + if (p4d_none(*p4d)) { + next = (addr + PAGE_SIZE) & PAGE_MASK; + continue; + } + get_page_bootmem(section_nr, p4d_page(*p4d), MIX_SECTION_INFO); + + pud = pud_offset(p4d, addr); if (pud_none(*pud)) { next = (addr + PAGE_SIZE) & PAGE_MASK; continue; diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 7aaa2635862d..e4f7b25df18e 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -9,12 +9,13 @@ #include <linux/bootmem.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/ioport.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/mmiotrace.h> #include <asm/cacheflush.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/fixmap.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> @@ -425,7 +426,8 @@ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr) /* Don't assume we're using swapper_pg_dir at this point */ pgd_t *base = __va(read_cr3()); pgd_t *pgd = &base[pgd_index(addr)]; - pud_t *pud = pud_offset(pgd, addr); + p4d_t *p4d = p4d_offset(pgd, addr); + pud_t *pud = pud_offset(p4d, addr); pmd_t *pmd = pmd_offset(pud, addr); return pmd; diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 8d63d7a104c3..0c7d8129bed6 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c @@ -1,3 +1,4 @@ +#define DISABLE_BRANCH_PROFILING #define pr_fmt(fmt) "kasan: " fmt #include <linux/bootmem.h> #include <linux/kasan.h> @@ -7,11 +8,12 @@ #include <linux/sched/task.h> #include <linux/vmalloc.h> +#include <asm/e820/types.h> #include <asm/tlbflush.h> #include <asm/sections.h> extern pgd_t early_level4_pgt[PTRS_PER_PGD]; -extern struct range pfn_mapped[E820_X_MAX]; +extern struct range pfn_mapped[E820_MAX_ENTRIES]; static int __init map_range(struct range *range) { @@ -32,8 +34,19 @@ static int __init map_range(struct range *range) static void __init clear_pgds(unsigned long start, unsigned long end) { - for (; start < end; start += PGDIR_SIZE) - pgd_clear(pgd_offset_k(start)); + pgd_t *pgd; + + for (; start < end; start += PGDIR_SIZE) { + pgd = pgd_offset_k(start); + /* + * With folded p4d, pgd_clear() is nop, use p4d_clear() + * instead. + */ + if (CONFIG_PGTABLE_LEVELS < 5) + p4d_clear(p4d_offset(pgd, start)); + else + pgd_clear(pgd); + } } static void __init kasan_map_early_shadow(pgd_t *pgd) @@ -43,8 +56,18 @@ static void __init kasan_map_early_shadow(pgd_t *pgd) unsigned long end = KASAN_SHADOW_END; for (i = pgd_index(start); start < end; i++) { - pgd[i] = __pgd(__pa_nodebug(kasan_zero_pud) - | _KERNPG_TABLE); + switch (CONFIG_PGTABLE_LEVELS) { + case 4: + pgd[i] = __pgd(__pa_nodebug(kasan_zero_pud) | + _KERNPG_TABLE); + break; + case 5: + pgd[i] = __pgd(__pa_nodebug(kasan_zero_p4d) | + _KERNPG_TABLE); + break; + default: + BUILD_BUG(); + } start += PGDIR_SIZE; } } @@ -72,6 +95,7 @@ void __init kasan_early_init(void) pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL; pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE; pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE; + p4dval_t p4d_val = __pa_nodebug(kasan_zero_pud) | _KERNPG_TABLE; for (i = 0; i < PTRS_PER_PTE; i++) kasan_zero_pte[i] = __pte(pte_val); @@ -82,6 +106,9 @@ void __init kasan_early_init(void) for (i = 0; i < PTRS_PER_PUD; i++) kasan_zero_pud[i] = __pud(pud_val); + for (i = 0; CONFIG_PGTABLE_LEVELS >= 5 && i < PTRS_PER_P4D; i++) + kasan_zero_p4d[i] = __p4d(p4d_val); + kasan_map_early_shadow(early_level4_pgt); kasan_map_early_shadow(init_level4_pgt); } @@ -103,7 +130,7 @@ void __init kasan_init(void) kasan_populate_zero_shadow((void *)KASAN_SHADOW_START, kasan_mem_to_shadow((void *)PAGE_OFFSET)); - for (i = 0; i < E820_X_MAX; i++) { + for (i = 0; i < E820_MAX_ENTRIES; i++) { if (pfn_mapped[i].end == 0) break; diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c index 887e57182716..aed206475aa7 100644 --- a/arch/x86/mm/kaslr.c +++ b/arch/x86/mm/kaslr.c @@ -48,7 +48,7 @@ static const unsigned long vaddr_start = __PAGE_OFFSET_BASE; #if defined(CONFIG_X86_ESPFIX64) static const unsigned long vaddr_end = ESPFIX_BASE_ADDR; #elif defined(CONFIG_EFI) -static const unsigned long vaddr_end = EFI_VA_START; +static const unsigned long vaddr_end = EFI_VA_END; #else static const unsigned long vaddr_end = __START_KERNEL_map; #endif @@ -105,7 +105,7 @@ void __init kernel_randomize_memory(void) */ BUILD_BUG_ON(vaddr_start >= vaddr_end); BUILD_BUG_ON(IS_ENABLED(CONFIG_X86_ESPFIX64) && - vaddr_end >= EFI_VA_START); + vaddr_end >= EFI_VA_END); BUILD_BUG_ON((IS_ENABLED(CONFIG_X86_ESPFIX64) || IS_ENABLED(CONFIG_EFI)) && vaddr_end >= __START_KERNEL_map); diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 7940166c799b..19ad095b41df 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -30,30 +30,44 @@ #include <linux/limits.h> #include <linux/sched/signal.h> #include <linux/sched/mm.h> +#include <linux/compat.h> #include <asm/elf.h> struct va_alignment __read_mostly va_align = { .flags = -1, }; -static unsigned long stack_maxrandom_size(void) +unsigned long tasksize_32bit(void) +{ + return IA32_PAGE_OFFSET; +} + +unsigned long tasksize_64bit(void) +{ + return TASK_SIZE_MAX; +} + +static unsigned long stack_maxrandom_size(unsigned long task_size) { unsigned long max = 0; if ((current->flags & PF_RANDOMIZE) && !(current->personality & ADDR_NO_RANDOMIZE)) { - max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT; + max = (-1UL) & __STACK_RND_MASK(task_size == tasksize_32bit()); + max <<= PAGE_SHIFT; } return max; } -/* - * Top of mmap area (just below the process stack). - * - * Leave an at least ~128 MB hole with possible stack randomization. - */ -#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size()) -#define MAX_GAP (TASK_SIZE/6*5) +#ifdef CONFIG_COMPAT +# define mmap32_rnd_bits mmap_rnd_compat_bits +# define mmap64_rnd_bits mmap_rnd_bits +#else +# define mmap32_rnd_bits mmap_rnd_bits +# define mmap64_rnd_bits mmap_rnd_bits +#endif + +#define SIZE_128M (128 * 1024 * 1024UL) static int mmap_is_legacy(void) { @@ -66,54 +80,91 @@ static int mmap_is_legacy(void) return sysctl_legacy_va_layout; } -unsigned long arch_mmap_rnd(void) +static unsigned long arch_rnd(unsigned int rndbits) { - unsigned long rnd; - - if (mmap_is_ia32()) -#ifdef CONFIG_COMPAT - rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1); -#else - rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); -#endif - else - rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); + return (get_random_long() & ((1UL << rndbits) - 1)) << PAGE_SHIFT; +} - return rnd << PAGE_SHIFT; +unsigned long arch_mmap_rnd(void) +{ + if (!(current->flags & PF_RANDOMIZE)) + return 0; + return arch_rnd(mmap_is_ia32() ? mmap32_rnd_bits : mmap64_rnd_bits); } -static unsigned long mmap_base(unsigned long rnd) +static unsigned long mmap_base(unsigned long rnd, unsigned long task_size) { unsigned long gap = rlimit(RLIMIT_STACK); + unsigned long gap_min, gap_max; + + /* + * Top of mmap area (just below the process stack). + * Leave an at least ~128 MB hole with possible stack randomization. + */ + gap_min = SIZE_128M + stack_maxrandom_size(task_size); + gap_max = (task_size / 6) * 5; - if (gap < MIN_GAP) - gap = MIN_GAP; - else if (gap > MAX_GAP) - gap = MAX_GAP; + if (gap < gap_min) + gap = gap_min; + else if (gap > gap_max) + gap = gap_max; + + return PAGE_ALIGN(task_size - gap - rnd); +} - return PAGE_ALIGN(TASK_SIZE - gap - rnd); +static unsigned long mmap_legacy_base(unsigned long rnd, + unsigned long task_size) +{ + return __TASK_UNMAPPED_BASE(task_size) + rnd; } /* * This function, called very early during the creation of a new * process VM image, sets up which VM layout function to use: */ +static void arch_pick_mmap_base(unsigned long *base, unsigned long *legacy_base, + unsigned long random_factor, unsigned long task_size) +{ + *legacy_base = mmap_legacy_base(random_factor, task_size); + if (mmap_is_legacy()) + *base = *legacy_base; + else + *base = mmap_base(random_factor, task_size); +} + void arch_pick_mmap_layout(struct mm_struct *mm) { - unsigned long random_factor = 0UL; + if (mmap_is_legacy()) + mm->get_unmapped_area = arch_get_unmapped_area; + else + mm->get_unmapped_area = arch_get_unmapped_area_topdown; - if (current->flags & PF_RANDOMIZE) - random_factor = arch_mmap_rnd(); + arch_pick_mmap_base(&mm->mmap_base, &mm->mmap_legacy_base, + arch_rnd(mmap64_rnd_bits), tasksize_64bit()); + +#ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES + /* + * The mmap syscall mapping base decision depends solely on the + * syscall type (64-bit or compat). This applies for 64bit + * applications and 32bit applications. The 64bit syscall uses + * mmap_base, the compat syscall uses mmap_compat_base. + */ + arch_pick_mmap_base(&mm->mmap_compat_base, &mm->mmap_compat_legacy_base, + arch_rnd(mmap32_rnd_bits), tasksize_32bit()); +#endif +} - mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor; +unsigned long get_mmap_base(int is_legacy) +{ + struct mm_struct *mm = current->mm; - if (mmap_is_legacy()) { - mm->mmap_base = mm->mmap_legacy_base; - mm->get_unmapped_area = arch_get_unmapped_area; - } else { - mm->mmap_base = mmap_base(random_factor); - mm->get_unmapped_area = arch_get_unmapped_area_topdown; +#ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES + if (in_compat_syscall()) { + return is_legacy ? mm->mmap_compat_legacy_base + : mm->mmap_compat_base; } +#endif + return is_legacy ? mm->mmap_legacy_base : mm->mmap_base; } const char *arch_vma_name(struct vm_area_struct *vma) diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index bef36622e408..4d434ddb75db 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c @@ -32,7 +32,7 @@ #include <linux/kallsyms.h> #include <asm/pgtable.h> #include <linux/mmiotrace.h> -#include <asm/e820.h> /* for ISA_START_ADDRESS */ +#include <asm/e820/api.h> /* for ISA_START_ADDRESS */ #include <linux/atomic.h> #include <linux/percpu.h> #include <linux/cpu.h> diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index 5126dfd52b18..1c34b767c84c 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c @@ -526,15 +526,7 @@ int mpx_handle_bd_fault(void) if (!kernel_managing_mpx_tables(current->mm)) return -EINVAL; - if (do_mpx_bt_fault()) { - force_sig(SIGSEGV, current); - /* - * The force_sig() is essentially "handling" this - * exception, so we do not pass up the error - * from do_mpx_bt_fault(). - */ - } - return 0; + return do_mpx_bt_fault(); } /* @@ -590,7 +582,7 @@ static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm, * we might run off the end of the bounds table if we are on * a 64-bit kernel and try to get 8 bytes. */ -int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret, +static int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret, long __user *bd_entry_ptr) { u32 bd_entry_32; diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 12dcad7297a5..25504d5aa816 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -12,7 +12,7 @@ #include <linux/sched.h> #include <linux/topology.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/proto.h> #include <asm/dma.h> #include <asm/amd_nb.h> @@ -201,7 +201,7 @@ static void __init alloc_node_data(int nid) nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES, MEMBLOCK_ALLOC_ACCESSIBLE); if (!nd_pa) { - pr_err("Cannot find %zu bytes in node %d\n", + pr_err("Cannot find %zu bytes in any node (initial node: %d)\n", nd_size, nid); return; } @@ -225,7 +225,7 @@ static void __init alloc_node_data(int nid) * numa_cleanup_meminfo - Cleanup a numa_meminfo * @mi: numa_meminfo to clean up * - * Sanitize @mi by merging and removing unncessary memblks. Also check for + * Sanitize @mi by merging and removing unnecessary memblks. Also check for * conflicts and clear unused memblks. * * RETURNS: diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 28d42130243c..56b22fa504df 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -15,7 +15,7 @@ #include <linux/pci.h> #include <linux/vmalloc.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/processor.h> #include <asm/tlbflush.h> #include <asm/sections.h> @@ -346,6 +346,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, unsigned int *level) { + p4d_t *p4d; pud_t *pud; pmd_t *pmd; @@ -354,7 +355,15 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, if (pgd_none(*pgd)) return NULL; - pud = pud_offset(pgd, address); + p4d = p4d_offset(pgd, address); + if (p4d_none(*p4d)) + return NULL; + + *level = PG_LEVEL_512G; + if (p4d_large(*p4d) || !p4d_present(*p4d)) + return (pte_t *)p4d; + + pud = pud_offset(p4d, address); if (pud_none(*pud)) return NULL; @@ -406,13 +415,18 @@ static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address, pmd_t *lookup_pmd_address(unsigned long address) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pgd = pgd_offset_k(address); if (pgd_none(*pgd)) return NULL; - pud = pud_offset(pgd, address); + p4d = p4d_offset(pgd, address); + if (p4d_none(*p4d) || p4d_large(*p4d) || !p4d_present(*p4d)) + return NULL; + + pud = pud_offset(p4d, address); if (pud_none(*pud) || pud_large(*pud) || !pud_present(*pud)) return NULL; @@ -477,11 +491,13 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) list_for_each_entry(page, &pgd_list, lru) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pgd = (pgd_t *)page_address(page) + pgd_index(address); - pud = pud_offset(pgd, address); + p4d = p4d_offset(pgd, address); + pud = pud_offset(p4d, address); pmd = pmd_offset(pud, address); set_pte_atomic((pte_t *)pmd, pte); } @@ -836,9 +852,9 @@ static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end) pud_clear(pud); } -static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end) +static void unmap_pud_range(p4d_t *p4d, unsigned long start, unsigned long end) { - pud_t *pud = pud_offset(pgd, start); + pud_t *pud = pud_offset(p4d, start); /* * Not on a GB page boundary? @@ -1004,8 +1020,8 @@ static long populate_pmd(struct cpa_data *cpa, return num_pages; } -static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd, - pgprot_t pgprot) +static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d, + pgprot_t pgprot) { pud_t *pud; unsigned long end; @@ -1026,7 +1042,7 @@ static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd, cur_pages = (pre_end - start) >> PAGE_SHIFT; cur_pages = min_t(int, (int)cpa->numpages, cur_pages); - pud = pud_offset(pgd, start); + pud = pud_offset(p4d, start); /* * Need a PMD page? @@ -1047,7 +1063,7 @@ static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd, if (cpa->numpages == cur_pages) return cur_pages; - pud = pud_offset(pgd, start); + pud = pud_offset(p4d, start); pud_pgprot = pgprot_4k_2_large(pgprot); /* @@ -1067,7 +1083,7 @@ static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd, if (start < end) { long tmp; - pud = pud_offset(pgd, start); + pud = pud_offset(p4d, start); if (pud_none(*pud)) if (alloc_pmd_page(pud)) return -1; @@ -1090,33 +1106,43 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr) { pgprot_t pgprot = __pgprot(_KERNPG_TABLE); pud_t *pud = NULL; /* shut up gcc */ + p4d_t *p4d; pgd_t *pgd_entry; long ret; pgd_entry = cpa->pgd + pgd_index(addr); + if (pgd_none(*pgd_entry)) { + p4d = (p4d_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK); + if (!p4d) + return -1; + + set_pgd(pgd_entry, __pgd(__pa(p4d) | _KERNPG_TABLE)); + } + /* * Allocate a PUD page and hand it down for mapping. */ - if (pgd_none(*pgd_entry)) { + p4d = p4d_offset(pgd_entry, addr); + if (p4d_none(*p4d)) { pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK); if (!pud) return -1; - set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE)); + set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE)); } pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr); pgprot_val(pgprot) |= pgprot_val(cpa->mask_set); - ret = populate_pud(cpa, addr, pgd_entry, pgprot); + ret = populate_pud(cpa, addr, p4d, pgprot); if (ret < 0) { /* * Leave the PUD page in place in case some other CPU or thread * already found it, but remove any useless entries we just * added to it. */ - unmap_pud_range(pgd_entry, addr, + unmap_pud_range(p4d, addr, addr + (cpa->numpages << PAGE_SHIFT)); return ret; } diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index efc32bc6862b..9b78685b66e6 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -10,6 +10,7 @@ #include <linux/seq_file.h> #include <linux/bootmem.h> #include <linux/debugfs.h> +#include <linux/ioport.h> #include <linux/kernel.h> #include <linux/pfn_t.h> #include <linux/slab.h> @@ -23,7 +24,7 @@ #include <asm/x86_init.h> #include <asm/pgtable.h> #include <asm/fcntl.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/mtrr.h> #include <asm/page.h> #include <asm/msr.h> diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 6cbdff26bb96..508a708eb9a6 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -81,6 +81,14 @@ void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud) paravirt_release_pud(__pa(pud) >> PAGE_SHIFT); tlb_remove_page(tlb, virt_to_page(pud)); } + +#if CONFIG_PGTABLE_LEVELS > 4 +void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d) +{ + paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT); + tlb_remove_page(tlb, virt_to_page(p4d)); +} +#endif /* CONFIG_PGTABLE_LEVELS > 4 */ #endif /* CONFIG_PGTABLE_LEVELS > 3 */ #endif /* CONFIG_PGTABLE_LEVELS > 2 */ @@ -120,7 +128,7 @@ static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd) references from swapper_pg_dir. */ if (CONFIG_PGTABLE_LEVELS == 2 || (CONFIG_PGTABLE_LEVELS == 3 && SHARED_KERNEL_PMD) || - CONFIG_PGTABLE_LEVELS == 4) { + CONFIG_PGTABLE_LEVELS >= 4) { clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY, swapper_pg_dir + KERNEL_PGD_BOUNDARY, KERNEL_PGD_PTRS); @@ -261,13 +269,15 @@ static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp) static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[]) { + p4d_t *p4d; pud_t *pud; int i; if (PREALLOCATED_PMDS == 0) /* Work around gcc-3.4.x bug */ return; - pud = pud_offset(pgd, 0); + p4d = p4d_offset(pgd, 0); + pud = pud_offset(p4d, 0); for (i = 0; i < PREALLOCATED_PMDS; i++, pud++) { pmd_t *pmd = pmds[i]; @@ -580,6 +590,28 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, } #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP +#ifdef CONFIG_X86_5LEVEL +/** + * p4d_set_huge - setup kernel P4D mapping + * + * No 512GB pages yet -- always return 0 + */ +int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot) +{ + return 0; +} + +/** + * p4d_clear_huge - clear kernel P4D mapping when it is set + * + * No 512GB pages yet -- always return 0 + */ +int p4d_clear_huge(p4d_t *p4d) +{ + return 0; +} +#endif + /** * pud_set_huge - setup kernel PUD mapping * diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index 9adce776852b..b9bd5b8b14fa 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c @@ -12,7 +12,7 @@ #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/fixmap.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/tlb.h> #include <asm/tlbflush.h> #include <asm/io.h> @@ -26,6 +26,7 @@ unsigned int __VMALLOC_RESERVE = 128 << 20; void set_pte_vaddr(unsigned long vaddr, pte_t pteval) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -35,7 +36,12 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pteval) BUG(); return; } - pud = pud_offset(pgd, vaddr); + p4d = p4d_offset(pgd, vaddr); + if (p4d_none(*p4d)) { + BUG(); + return; + } + pud = pud_offset(p4d, vaddr); if (pud_none(*pud)) { BUG(); return; diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 35fe69529bc1..3ea20d61b523 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -18,7 +18,7 @@ #include <linux/mm.h> #include <asm/proto.h> #include <asm/numa.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/apic.h> #include <asm/uv/uv.h> diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index a7655f6caf7d..6e7bedf69af7 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -263,8 +263,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask, { struct flush_tlb_info info; - if (end == 0) - end = start + PAGE_SIZE; info.flush_mm = mm; info.flush_start = start; info.flush_end = end; @@ -289,23 +287,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask, smp_call_function_many(cpumask, flush_tlb_func, &info, 1); } -void flush_tlb_current_task(void) -{ - struct mm_struct *mm = current->mm; - - preempt_disable(); - - count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); - - /* This is an implicit full barrier that synchronizes with switch_mm. */ - local_flush_tlb(); - - trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL); - if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); - preempt_enable(); -} - /* * See Documentation/x86/tlb.txt for details. We choose 33 * because it is large enough to cover the vast majority (at @@ -326,6 +307,12 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long base_pages_to_flush = TLB_FLUSH_ALL; preempt_disable(); + + if ((end != TLB_FLUSH_ALL) && !(vmflag & VM_HUGETLB)) + base_pages_to_flush = (end - start) >> PAGE_SHIFT; + if (base_pages_to_flush > tlb_single_page_flush_ceiling) + base_pages_to_flush = TLB_FLUSH_ALL; + if (current->active_mm != mm) { /* Synchronize with switch_mm. */ smp_mb(); @@ -342,15 +329,11 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, goto out; } - if ((end != TLB_FLUSH_ALL) && !(vmflag & VM_HUGETLB)) - base_pages_to_flush = (end - start) >> PAGE_SHIFT; - /* * Both branches below are implicit full barriers (MOV to CR or * INVLPG) that synchronize with switch_mm. */ - if (base_pages_to_flush > tlb_single_page_flush_ceiling) { - base_pages_to_flush = TLB_FLUSH_ALL; + if (base_pages_to_flush == TLB_FLUSH_ALL) { count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); local_flush_tlb(); } else { @@ -393,7 +376,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start) } if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, start, 0UL); + flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE); preempt_enable(); } diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 32322ce9b405..14f840df1d95 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -490,13 +490,6 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, break; case BPF_LD | BPF_IMM | BPF_DW: - if (insn[1].code != 0 || insn[1].src_reg != 0 || - insn[1].dst_reg != 0 || insn[1].off != 0) { - /* verifier must catch invalid insns */ - pr_err("invalid BPF_LD_IMM64 insn\n"); - return -EINVAL; - } - /* optimization: if imm64 is zero, use 'xor <dst>,<dst>' * to save 7 bytes. */ diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae0a8f0..190e718694b1 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(&dev->enable_cnt) >= 0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops) diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 0a9f2caf358f..6fa84d531f4f 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -34,7 +34,7 @@ #include <linux/bootmem.h> #include <asm/pat.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/pci_x86.h> #include <asm/io_apic.h> @@ -398,7 +398,7 @@ void __init pcibios_resource_survey(void) list_for_each_entry(bus, &pci_root_buses, node) pcibios_allocate_resources(bus, 1); - e820_reserve_resources_late(); + e820__reserve_resources_late(); /* * Insert the IO APIC resources after PCI initialization has * occurred to handle IO APICS that are mapped in on a BAR in diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index dd30b7e08bc2..d1b47d5bc9c3 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -18,7 +18,7 @@ #include <linux/slab.h> #include <linux/mutex.h> #include <linux/rculist.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/pci_x86.h> #include <asm/acpi.h> @@ -423,7 +423,7 @@ static acpi_status find_mboard_resource(acpi_handle handle, u32 lvl, return AE_OK; } -static int is_acpi_reserved(u64 start, u64 end, unsigned not_used) +static bool is_acpi_reserved(u64 start, u64 end, unsigned not_used) { struct resource mcfg_res; @@ -440,11 +440,11 @@ static int is_acpi_reserved(u64 start, u64 end, unsigned not_used) return mcfg_res.flags; } -typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); +typedef bool (*check_reserved_t)(u64 start, u64 end, unsigned type); -static int __ref is_mmconf_reserved(check_reserved_t is_reserved, - struct pci_mmcfg_region *cfg, - struct device *dev, int with_e820) +static bool __ref is_mmconf_reserved(check_reserved_t is_reserved, + struct pci_mmcfg_region *cfg, + struct device *dev, int with_e820) { u64 addr = cfg->res.start; u64 size = resource_size(&cfg->res); @@ -452,7 +452,7 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved, int num_buses; char *method = with_e820 ? "E820" : "ACPI motherboard resources"; - while (!is_reserved(addr, addr + size, E820_RESERVED)) { + while (!is_reserved(addr, addr + size, E820_TYPE_RESERVED)) { size >>= 1; if (size < (16UL<<20)) break; @@ -494,8 +494,8 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved, return 1; } -static int __ref pci_mmcfg_check_reserved(struct device *dev, - struct pci_mmcfg_region *cfg, int early) +static bool __ref +pci_mmcfg_check_reserved(struct device *dev, struct pci_mmcfg_region *cfg, int early) { if (!early && !acpi_disabled) { if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0)) @@ -514,7 +514,7 @@ static int __ref pci_mmcfg_check_reserved(struct device *dev, } /* - * e820_all_mapped() is marked as __init. + * e820__mapped_all() is marked as __init. * All entries from ACPI MCFG table have been checked at boot time. * For MCFG information constructed from hotpluggable host bridge's * _CBA method, just assume it's reserved. @@ -525,7 +525,7 @@ static int __ref pci_mmcfg_check_reserved(struct device *dev, /* Don't try to do this check unless configuration type 1 is available. how about type 2 ?*/ if (raw_pci_ops) - return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1); + return is_mmconf_reserved(e820__mapped_all, cfg, dev, 1); return 0; } diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index 43984bc1665a..3e9e166f6408 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -12,7 +12,7 @@ #include <linux/pci.h> #include <linux/init.h> #include <linux/rcupdate.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/pci_x86.h> /* Assume systems with more busses have correct MCFG */ diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index bea52496aea6..f1c1aa0430ae 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -10,7 +10,7 @@ #include <linux/acpi.h> #include <linux/bitmap.h> #include <linux/rcupdate.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/pci_x86.h> #define PREFIX "PCI: " diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index 1d97cea3b3a4..29e9ba6ace9d 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c @@ -7,7 +7,9 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/uaccess.h> + #include <asm/pci_x86.h> +#include <asm/e820/types.h> #include <asm/pci-functions.h> #include <asm/cacheflush.h> diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index e1fb269c87af..292ab0364a89 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -234,23 +234,14 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 1; for_each_pci_msi_entry(msidesc, dev) { - __pci_read_msi_msg(msidesc, &msg); - pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | - ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); - if (msg.data != XEN_PIRQ_MSI_DATA || - xen_irq_from_pirq(pirq) < 0) { - pirq = xen_allocate_pirq_msi(dev, msidesc); - if (pirq < 0) { - irq = -ENODEV; - goto error; - } - xen_msi_compose_msg(dev, pirq, &msg); - __pci_write_msi_msg(msidesc, &msg); - dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); - } else { - dev_dbg(&dev->dev, - "xen: msi already bound to pirq=%d\n", pirq); + pirq = xen_allocate_pirq_msi(dev, msidesc); + if (pirq < 0) { + irq = -ENODEV; + goto error; } + xen_msi_compose_msg(dev, pirq, &msg); + __pci_write_msi_msg(msidesc, &msg); + dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, (type == PCI_CAP_ID_MSI) ? nvec : 1, (type == PCI_CAP_ID_MSIX) ? diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index 066619b0700c..f1d83b34c329 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile @@ -1,6 +1,5 @@ OBJECT_FILES_NON_STANDARD_efi_thunk_$(BITS).o := y obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o -obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c deleted file mode 100644 index 04ca8764f0c0..000000000000 --- a/arch/x86/platform/efi/efi-bgrt.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012 Intel Corporation - * Author: Josh Triplett <josh@joshtriplett.org> - * - * Based on the bgrt driver: - * Copyright 2012 Red Hat, Inc <mjg@redhat.com> - * Author: Matthew Garrett - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/efi.h> -#include <linux/efi-bgrt.h> - -struct acpi_table_bgrt bgrt_tab; -size_t __initdata bgrt_image_size; - -struct bmp_header { - u16 id; - u32 size; -} __packed; - -void __init efi_bgrt_init(struct acpi_table_header *table) -{ - void *image; - struct bmp_header bmp_header; - struct acpi_table_bgrt *bgrt = &bgrt_tab; - - if (acpi_disabled) - return; - - if (table->length < sizeof(bgrt_tab)) { - pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", - table->length, sizeof(bgrt_tab)); - return; - } - *bgrt = *(struct acpi_table_bgrt *)table; - if (bgrt->version != 1) { - pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n", - bgrt->version); - goto out; - } - if (bgrt->status & 0xfe) { - pr_notice("Ignoring BGRT: reserved status bits are non-zero %u\n", - bgrt->status); - goto out; - } - if (bgrt->image_type != 0) { - pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n", - bgrt->image_type); - goto out; - } - if (!bgrt->image_address) { - pr_notice("Ignoring BGRT: null image address\n"); - goto out; - } - - image = early_memremap(bgrt->image_address, sizeof(bmp_header)); - if (!image) { - pr_notice("Ignoring BGRT: failed to map image header memory\n"); - goto out; - } - - memcpy(&bmp_header, image, sizeof(bmp_header)); - early_memunmap(image, sizeof(bmp_header)); - if (bmp_header.id != 0x4d42) { - pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n", - bmp_header.id); - goto out; - } - bgrt_image_size = bmp_header.size; - efi_mem_reserve(bgrt->image_address, bgrt_image_size); - - return; -out: - memset(bgrt, 0, sizeof(bgrt_tab)); -} diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 565dff3c9a12..a15cf815ac4e 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -47,6 +47,7 @@ #include <asm/setup.h> #include <asm/efi.h> +#include <asm/e820/api.h> #include <asm/time.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> @@ -139,21 +140,21 @@ static void __init do_add_efi_memmap(void) case EFI_BOOT_SERVICES_DATA: case EFI_CONVENTIONAL_MEMORY: if (md->attribute & EFI_MEMORY_WB) - e820_type = E820_RAM; + e820_type = E820_TYPE_RAM; else - e820_type = E820_RESERVED; + e820_type = E820_TYPE_RESERVED; break; case EFI_ACPI_RECLAIM_MEMORY: - e820_type = E820_ACPI; + e820_type = E820_TYPE_ACPI; break; case EFI_ACPI_MEMORY_NVS: - e820_type = E820_NVS; + e820_type = E820_TYPE_NVS; break; case EFI_UNUSABLE_MEMORY: - e820_type = E820_UNUSABLE; + e820_type = E820_TYPE_UNUSABLE; break; case EFI_PERSISTENT_MEMORY: - e820_type = E820_PMEM; + e820_type = E820_TYPE_PMEM; break; default: /* @@ -161,12 +162,12 @@ static void __init do_add_efi_memmap(void) * EFI_RUNTIME_SERVICES_DATA EFI_MEMORY_MAPPED_IO * EFI_MEMORY_MAPPED_IO_PORT_SPACE EFI_PAL_CODE */ - e820_type = E820_RESERVED; + e820_type = E820_TYPE_RESERVED; break; } - e820_add_region(start, size, e820_type); + e820__range_add(start, size, e820_type); } - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); + e820__update_table(e820_table); } int __init efi_memblock_x86_reserve_range(void) diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index cef39b097649..3481268da3d0 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -68,7 +68,7 @@ pgd_t * __init efi_call_phys_prolog(void) load_cr3(initial_page_table); __flush_tlb_all(); - gdt_descr.address = __pa(get_cpu_gdt_table(0)); + gdt_descr.address = get_cpu_gdt_paddr(0); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); @@ -79,7 +79,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) { struct desc_ptr gdt_descr; - gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); + gdt_descr.address = (unsigned long)get_cpu_gdt_rw(0); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index a4695da42d77..c488625c9712 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -35,7 +35,7 @@ #include <asm/setup.h> #include <asm/page.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/proto.h> @@ -47,7 +47,7 @@ #include <asm/pgalloc.h> /* - * We allocate runtime services regions bottom-up, starting from -4G, i.e. + * We allocate runtime services regions top-down, starting from -4G, i.e. * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G. */ static u64 efi_va = EFI_VA_START; @@ -135,6 +135,7 @@ static pgd_t *efi_pgd; int __init efi_alloc_page_tables(void) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; gfp_t gfp_mask; @@ -147,15 +148,20 @@ int __init efi_alloc_page_tables(void) return -ENOMEM; pgd = efi_pgd + pgd_index(EFI_VA_END); + p4d = p4d_alloc(&init_mm, pgd, EFI_VA_END); + if (!p4d) { + free_page((unsigned long)efi_pgd); + return -ENOMEM; + } - pud = pud_alloc_one(NULL, 0); + pud = pud_alloc(&init_mm, p4d, EFI_VA_END); if (!pud) { + if (CONFIG_PGTABLE_LEVELS > 4) + free_page((unsigned long) pgd_page_vaddr(*pgd)); free_page((unsigned long)efi_pgd); return -ENOMEM; } - pgd_populate(NULL, pgd, pud); - return 0; } @@ -166,6 +172,7 @@ void efi_sync_low_kernel_mappings(void) { unsigned num_entries; pgd_t *pgd_k, *pgd_efi; + p4d_t *p4d_k, *p4d_efi; pud_t *pud_k, *pud_efi; if (efi_enabled(EFI_OLD_MEMMAP)) @@ -190,23 +197,37 @@ void efi_sync_low_kernel_mappings(void) memcpy(pgd_efi, pgd_k, sizeof(pgd_t) * num_entries); /* + * As with PGDs, we share all P4D entries apart from the one entry + * that covers the EFI runtime mapping space. + */ + BUILD_BUG_ON(p4d_index(EFI_VA_END) != p4d_index(MODULES_END)); + BUILD_BUG_ON((EFI_VA_START & P4D_MASK) != (EFI_VA_END & P4D_MASK)); + + pgd_efi = efi_pgd + pgd_index(EFI_VA_END); + pgd_k = pgd_offset_k(EFI_VA_END); + p4d_efi = p4d_offset(pgd_efi, 0); + p4d_k = p4d_offset(pgd_k, 0); + + num_entries = p4d_index(EFI_VA_END); + memcpy(p4d_efi, p4d_k, sizeof(p4d_t) * num_entries); + + /* * We share all the PUD entries apart from those that map the * EFI regions. Copy around them. */ BUILD_BUG_ON((EFI_VA_START & ~PUD_MASK) != 0); BUILD_BUG_ON((EFI_VA_END & ~PUD_MASK) != 0); - pgd_efi = efi_pgd + pgd_index(EFI_VA_END); - pud_efi = pud_offset(pgd_efi, 0); - - pgd_k = pgd_offset_k(EFI_VA_END); - pud_k = pud_offset(pgd_k, 0); + p4d_efi = p4d_offset(pgd_efi, EFI_VA_END); + p4d_k = p4d_offset(pgd_k, EFI_VA_END); + pud_efi = pud_offset(p4d_efi, 0); + pud_k = pud_offset(p4d_k, 0); num_entries = pud_index(EFI_VA_END); memcpy(pud_efi, pud_k, sizeof(pud_t) * num_entries); - pud_efi = pud_offset(pgd_efi, EFI_VA_START); - pud_k = pud_offset(pgd_k, EFI_VA_START); + pud_efi = pud_offset(p4d_efi, EFI_VA_START); + pud_k = pud_offset(p4d_k, EFI_VA_START); num_entries = PTRS_PER_PUD - pud_index(EFI_VA_START); memcpy(pud_efi, pud_k, sizeof(pud_t) * num_entries); diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 30031d5293c4..26615991d69c 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -11,6 +11,8 @@ #include <linux/bootmem.h> #include <linux/acpi.h> #include <linux/dmi.h> + +#include <asm/e820/api.h> #include <asm/efi.h> #include <asm/uv/uv.h> @@ -201,6 +203,10 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) return; } + /* No need to reserve regions that will never be freed. */ + if (md.attribute & EFI_MEMORY_RUNTIME) + return; + size += addr % EFI_PAGE_SIZE; size = round_up(size, EFI_PAGE_SIZE); addr = round_down(addr, EFI_PAGE_SIZE); @@ -240,14 +246,14 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) * else. We must only reserve (and then free) regions: * * - Not within any part of the kernel - * - Not the BIOS reserved area (E820_RESERVED, E820_NVS, etc) + * - Not the BIOS reserved area (E820_TYPE_RESERVED, E820_TYPE_NVS, etc) */ static bool can_free_region(u64 start, u64 size) { if (start + size > __pa_symbol(_text) && start <= __pa_symbol(_end)) return false; - if (!e820_all_mapped(start, start+size, E820_RAM)) + if (!e820__mapped_all(start, start+size, E820_TYPE_RAM)) return false; return true; @@ -280,7 +286,7 @@ void __init efi_reserve_boot_services(void) * A good example of a critical region that must not be * freed is page zero (first 4Kb of memory), which may * contain boot services code/data but is marked - * E820_RESERVED by trim_bios_range(). + * E820_TYPE_RESERVED by trim_bios_range(). */ if (!already_reserved) { memblock_reserve(start, size); diff --git a/arch/x86/platform/intel-mid/device_libs/Makefile b/arch/x86/platform/intel-mid/device_libs/Makefile index a7dbec4dce27..53e0235e308f 100644 --- a/arch/x86/platform/intel-mid/device_libs/Makefile +++ b/arch/x86/platform/intel-mid/device_libs/Makefile @@ -2,8 +2,9 @@ obj-$(subst m,y,$(CONFIG_PINCTRL_MERRIFIELD)) += platform_mrfld_pinctrl.o # SDHCI Devices obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += platform_mrfld_sd.o -# WiFi +# WiFi + BT obj-$(subst m,y,$(CONFIG_BRCMFMAC_SDIO)) += platform_bcm43xx.o +obj-$(subst m,y,$(CONFIG_BT_HCIUART_BCM)) += platform_bt.o # IPC Devices obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o obj-$(subst m,y,$(CONFIG_SND_MFLD_MACHINE)) += platform_msic_audio.o @@ -26,5 +27,6 @@ obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_pcal9555a.o obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o # MISC Devices obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o +obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_mrfld_power_btn.o obj-$(subst m,y,$(CONFIG_RTC_DRV_CMOS)) += platform_mrfld_rtc.o obj-$(subst m,y,$(CONFIG_INTEL_MID_WATCHDOG)) += platform_mrfld_wdt.o diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bt.c b/arch/x86/platform/intel-mid/device_libs/platform_bt.c new file mode 100644 index 000000000000..5a0483e7bf66 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_bt.c @@ -0,0 +1,108 @@ +/* + * Bluetooth platform data initialization file + * + * (C) Copyright 2017 Intel Corporation + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include <linux/gpio/machine.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + +#include <asm/cpu_device_id.h> +#include <asm/intel-family.h> +#include <asm/intel-mid.h> + +struct bt_sfi_data { + struct device *dev; + const char *name; + int (*setup)(struct bt_sfi_data *ddata); +}; + +static struct gpiod_lookup_table tng_bt_sfi_gpio_table = { + .dev_id = "hci_bcm", + .table = { + GPIO_LOOKUP("0000:00:0c.0", -1, "device-wakeup", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("0000:00:0c.0", -1, "shutdown", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("0000:00:0c.0", -1, "host-wakeup", GPIO_ACTIVE_HIGH), + { }, + }, +}; + +#define TNG_BT_SFI_GPIO_DEVICE_WAKEUP "bt_wakeup" +#define TNG_BT_SFI_GPIO_SHUTDOWN "BT-reset" +#define TNG_BT_SFI_GPIO_HOST_WAKEUP "bt_uart_enable" + +static int __init tng_bt_sfi_setup(struct bt_sfi_data *ddata) +{ + struct gpiod_lookup_table *table = &tng_bt_sfi_gpio_table; + struct gpiod_lookup *lookup = table->table; + struct pci_dev *pdev; + + /* Connected to /dev/ttyS0 */ + pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(4, 1)); + if (!pdev) + return -ENODEV; + + ddata->dev = &pdev->dev; + ddata->name = table->dev_id; + + lookup[0].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_DEVICE_WAKEUP); + lookup[1].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_SHUTDOWN); + lookup[2].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_HOST_WAKEUP); + + gpiod_add_lookup_table(table); + return 0; +} + +static struct bt_sfi_data tng_bt_sfi_data __initdata = { + .setup = tng_bt_sfi_setup, +}; + +#define ICPU(model, ddata) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata } + +static const struct x86_cpu_id bt_sfi_cpu_ids[] = { + ICPU(INTEL_FAM6_ATOM_MERRIFIELD, tng_bt_sfi_data), + {} +}; + +static int __init bt_sfi_init(void) +{ + struct platform_device_info info; + struct platform_device *pdev; + const struct x86_cpu_id *id; + struct bt_sfi_data *ddata; + int ret; + + id = x86_match_cpu(bt_sfi_cpu_ids); + if (!id) + return -ENODEV; + + ddata = (struct bt_sfi_data *)id->driver_data; + if (!ddata) + return -ENODEV; + + ret = ddata->setup(ddata); + if (ret) + return ret; + + memset(&info, 0, sizeof(info)); + info.fwnode = ddata->dev->fwnode; + info.parent = ddata->dev; + info.name = ddata->name, + info.id = PLATFORM_DEVID_NONE, + + pdev = platform_device_register_full(&info); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + dev_info(ddata->dev, "Registered Bluetooth device: %s\n", ddata->name); + return 0; +} +device_initcall(bt_sfi_init); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_power_btn.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_power_btn.c new file mode 100644 index 000000000000..a6c3705a28ad --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_power_btn.c @@ -0,0 +1,82 @@ +/* + * Intel Merrifield power button support + * + * (C) Copyright 2017 Intel Corporation + * + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/sfi.h> + +#include <asm/intel-mid.h> +#include <asm/intel_scu_ipc.h> + +static struct resource mrfld_power_btn_resources[] = { + { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mrfld_power_btn_dev = { + .name = "msic_power_btn", + .id = PLATFORM_DEVID_NONE, + .num_resources = ARRAY_SIZE(mrfld_power_btn_resources), + .resource = mrfld_power_btn_resources, +}; + +static int mrfld_power_btn_scu_status_change(struct notifier_block *nb, + unsigned long code, void *data) +{ + if (code == SCU_DOWN) { + platform_device_unregister(&mrfld_power_btn_dev); + return 0; + } + + return platform_device_register(&mrfld_power_btn_dev); +} + +static struct notifier_block mrfld_power_btn_scu_notifier = { + .notifier_call = mrfld_power_btn_scu_status_change, +}; + +static int __init register_mrfld_power_btn(void) +{ + if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER) + return -ENODEV; + + /* + * We need to be sure that the SCU IPC is ready before + * PMIC power button device can be registered: + */ + intel_scu_notifier_add(&mrfld_power_btn_scu_notifier); + + return 0; +} +arch_initcall(register_mrfld_power_btn); + +static void __init *mrfld_power_btn_platform_data(void *info) +{ + struct resource *res = mrfld_power_btn_resources; + struct sfi_device_table_entry *pentry = info; + + res->start = res->end = pentry->irq; + return NULL; +} + +static const struct devs_id mrfld_power_btn_dev_id __initconst = { + .name = "bcove_power_btn", + .type = SFI_DEV_TYPE_IPC, + .delay = 1, + .msic = 1, + .get_platform_data = &mrfld_power_btn_platform_data, +}; + +sfi_device(mrfld_power_btn_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c index 86edd1e941eb..9e304e2ea4f5 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c @@ -19,7 +19,7 @@ #include <asm/intel_scu_ipc.h> #include <asm/io_apic.h> -#define TANGIER_EXT_TIMER0_MSI 15 +#define TANGIER_EXT_TIMER0_MSI 12 static struct platform_device wdt_dev = { .name = "intel_mid_wdt", diff --git a/arch/x86/platform/intel-mid/mfld.c b/arch/x86/platform/intel-mid/mfld.c index e793fe509971..e42978d4deaf 100644 --- a/arch/x86/platform/intel-mid/mfld.c +++ b/arch/x86/platform/intel-mid/mfld.c @@ -17,16 +17,6 @@ #include "intel_mid_weak_decls.h" -static void penwell_arch_setup(void); -/* penwell arch ops */ -static struct intel_mid_ops penwell_ops = { - .arch_setup = penwell_arch_setup, -}; - -static void mfld_power_off(void) -{ -} - static unsigned long __init mfld_calibrate_tsc(void) { unsigned long fast_calibrate; @@ -63,9 +53,12 @@ static unsigned long __init mfld_calibrate_tsc(void) static void __init penwell_arch_setup(void) { x86_platform.calibrate_tsc = mfld_calibrate_tsc; - pm_power_off = mfld_power_off; } +static struct intel_mid_ops penwell_ops = { + .arch_setup = penwell_arch_setup, +}; + void *get_penwell_ops(void) { return &penwell_ops; diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 766d4d3529a1..42e65fee5673 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -23,28 +23,7 @@ #include <asm/irq_vectors.h> #include <asm/timer.h> -static struct bau_operations ops; - -static struct bau_operations uv123_bau_ops = { - .bau_gpa_to_offset = uv_gpa_to_offset, - .read_l_sw_ack = read_mmr_sw_ack, - .read_g_sw_ack = read_gmmr_sw_ack, - .write_l_sw_ack = write_mmr_sw_ack, - .write_g_sw_ack = write_gmmr_sw_ack, - .write_payload_first = write_mmr_payload_first, - .write_payload_last = write_mmr_payload_last, -}; - -static struct bau_operations uv4_bau_ops = { - .bau_gpa_to_offset = uv_gpa_to_soc_phys_ram, - .read_l_sw_ack = read_mmr_proc_sw_ack, - .read_g_sw_ack = read_gmmr_proc_sw_ack, - .write_l_sw_ack = write_mmr_proc_sw_ack, - .write_g_sw_ack = write_gmmr_proc_sw_ack, - .write_payload_first = write_mmr_proc_payload_first, - .write_payload_last = write_mmr_proc_payload_last, -}; - +static struct bau_operations ops __ro_after_init; /* timeouts in nanoseconds (indexed by UVH_AGING_PRESCALE_SEL urgency7 30:28) */ static int timeout_base_ns[] = { @@ -548,11 +527,12 @@ static unsigned long uv1_read_status(unsigned long mmr_offset, int right_shift) * return COMPLETE, RETRY(PLUGGED or TIMEOUT) or GIVEUP */ static int uv1_wait_completion(struct bau_desc *bau_desc, - unsigned long mmr_offset, int right_shift, struct bau_control *bcp, long try) { unsigned long descriptor_status; cycles_t ttm; + u64 mmr_offset = bcp->status_mmr; + int right_shift = bcp->status_index; struct ptc_stats *stat = bcp->statp; descriptor_status = uv1_read_status(mmr_offset, right_shift); @@ -640,11 +620,12 @@ int handle_uv2_busy(struct bau_control *bcp) } static int uv2_3_wait_completion(struct bau_desc *bau_desc, - unsigned long mmr_offset, int right_shift, struct bau_control *bcp, long try) { unsigned long descriptor_stat; cycles_t ttm; + u64 mmr_offset = bcp->status_mmr; + int right_shift = bcp->status_index; int desc = bcp->uvhub_cpu; long busy_reps = 0; struct ptc_stats *stat = bcp->statp; @@ -706,28 +687,59 @@ static int uv2_3_wait_completion(struct bau_desc *bau_desc, } /* - * There are 2 status registers; each and array[32] of 2 bits. Set up for - * which register to read and position in that register based on cpu in - * current hub. + * Returns the status of current BAU message for cpu desc as a bit field + * [Error][Busy][Aux] */ -static int wait_completion(struct bau_desc *bau_desc, struct bau_control *bcp, long try) +static u64 read_status(u64 status_mmr, int index, int desc) { - int right_shift; - unsigned long mmr_offset; + u64 stat; + + stat = ((read_lmmr(status_mmr) >> index) & UV_ACT_STATUS_MASK) << 1; + stat |= (read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_2) >> desc) & 0x1; + + return stat; +} + +static int uv4_wait_completion(struct bau_desc *bau_desc, + struct bau_control *bcp, long try) +{ + struct ptc_stats *stat = bcp->statp; + u64 descriptor_stat; + u64 mmr = bcp->status_mmr; + int index = bcp->status_index; int desc = bcp->uvhub_cpu; - if (desc < UV_CPUS_PER_AS) { - mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0; - right_shift = desc * UV_ACT_STATUS_SIZE; - } else { - mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1; - right_shift = ((desc - UV_CPUS_PER_AS) * UV_ACT_STATUS_SIZE); - } + descriptor_stat = read_status(mmr, index, desc); - if (bcp->uvhub_version == 1) - return uv1_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try); - else - return uv2_3_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try); + /* spin on the status MMR, waiting for it to go idle */ + while (descriptor_stat != UV2H_DESC_IDLE) { + switch (descriptor_stat) { + case UV2H_DESC_SOURCE_TIMEOUT: + stat->s_stimeout++; + return FLUSH_GIVEUP; + + case UV2H_DESC_DEST_TIMEOUT: + stat->s_dtimeout++; + bcp->conseccompletes = 0; + return FLUSH_RETRY_TIMEOUT; + + case UV2H_DESC_DEST_STRONG_NACK: + stat->s_plugged++; + bcp->conseccompletes = 0; + return FLUSH_RETRY_PLUGGED; + + case UV2H_DESC_DEST_PUT_ERR: + bcp->conseccompletes = 0; + return FLUSH_GIVEUP; + + default: + /* descriptor_stat is still BUSY */ + cpu_relax(); + } + descriptor_stat = read_status(mmr, index, desc); + } + bcp->conseccompletes++; + return FLUSH_COMPLETE; } /* @@ -918,7 +930,7 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp, struct uv1_bau_msg_header *uv1_hdr = NULL; struct uv2_3_bau_msg_header *uv2_3_hdr = NULL; - if (bcp->uvhub_version == 1) { + if (bcp->uvhub_version == UV_BAU_V1) { uv1 = 1; uv1_throttle(hmaster, stat); } @@ -958,7 +970,7 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp, write_mmr_activation(index); try++; - completion_stat = wait_completion(bau_desc, bcp, try); + completion_stat = ops.wait_completion(bau_desc, bcp, try); handle_cmplt(completion_stat, bau_desc, bcp, hmaster, stat); @@ -1114,15 +1126,12 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, unsigned long end, unsigned int cpu) { - int locals = 0; - int remotes = 0; - int hubs = 0; + int locals = 0, remotes = 0, hubs = 0; struct bau_desc *bau_desc; struct cpumask *flush_mask; struct ptc_stats *stat; struct bau_control *bcp; - unsigned long descriptor_status; - unsigned long status; + unsigned long descriptor_status, status, address; bcp = &per_cpu(bau_control, cpu); @@ -1171,10 +1180,24 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, record_send_statistics(stat, locals, hubs, remotes, bau_desc); if (!end || (end - start) <= PAGE_SIZE) - bau_desc->payload.address = start; + address = start; else - bau_desc->payload.address = TLB_FLUSH_ALL; - bau_desc->payload.sending_cpu = cpu; + address = TLB_FLUSH_ALL; + + switch (bcp->uvhub_version) { + case UV_BAU_V1: + case UV_BAU_V2: + case UV_BAU_V3: + bau_desc->payload.uv1_2_3.address = address; + bau_desc->payload.uv1_2_3.sending_cpu = cpu; + break; + case UV_BAU_V4: + bau_desc->payload.uv4.address = address; + bau_desc->payload.uv4.sending_cpu = cpu; + bau_desc->payload.uv4.qualifier = BAU_DESC_QUALIFIER; + break; + } + /* * uv_flush_send_and_wait returns 0 if all cpu's were messaged, * or 1 if it gave up and the original cpumask should be returned. @@ -1296,7 +1319,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs) msgdesc.msg_slot = msg - msgdesc.queue_first; msgdesc.msg = msg; - if (bcp->uvhub_version == 2) + if (bcp->uvhub_version == UV_BAU_V2) process_uv2_message(&msgdesc, bcp); else /* no error workaround for uv1 or uv3 */ @@ -1838,7 +1861,7 @@ static void pq_init(int node, int pnode) * and the payload queue tail must be maintained by the kernel. */ bcp = &per_cpu(bau_control, smp_processor_id()); - if (bcp->uvhub_version <= 3) { + if (bcp->uvhub_version <= UV_BAU_V3) { tail = first; gnode = uv_gpa_to_gnode(uv_gpa(pqp)); first = (gnode << UV_PAYLOADQ_GNODE_SHIFT) | tail; @@ -1847,7 +1870,6 @@ static void pq_init(int node, int pnode) ops.write_payload_first(pnode, first); ops.write_payload_last(pnode, last); - ops.write_g_sw_ack(pnode, 0xffffUL); /* in effect, all msg_type's are set to MSG_NOOP */ memset(pqp, 0, sizeof(struct bau_pq_entry) * DEST_Q_SIZE); @@ -2035,8 +2057,7 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp, struct bau_control **smasterp, struct bau_control **hmasterp) { - int i; - int cpu; + int i, cpu, uvhub_cpu; struct bau_control *bcp; for (i = 0; i < sdp->num_cpus; i++) { @@ -2053,19 +2074,33 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp, bcp->socket_master = *smasterp; bcp->uvhub = bdp->uvhub; if (is_uv1_hub()) - bcp->uvhub_version = 1; + bcp->uvhub_version = UV_BAU_V1; else if (is_uv2_hub()) - bcp->uvhub_version = 2; + bcp->uvhub_version = UV_BAU_V2; else if (is_uv3_hub()) - bcp->uvhub_version = 3; + bcp->uvhub_version = UV_BAU_V3; else if (is_uv4_hub()) - bcp->uvhub_version = 4; + bcp->uvhub_version = UV_BAU_V4; else { pr_emerg("uvhub version not 1, 2, 3, or 4\n"); return 1; } bcp->uvhub_master = *hmasterp; - bcp->uvhub_cpu = uv_cpu_blade_processor_id(cpu); + uvhub_cpu = uv_cpu_blade_processor_id(cpu); + bcp->uvhub_cpu = uvhub_cpu; + + /* + * The ERROR and BUSY status registers are located pairwise over + * the STATUS_0 and STATUS_1 mmrs; each an array[32] of 2 bits. + */ + if (uvhub_cpu < UV_CPUS_PER_AS) { + bcp->status_mmr = UVH_LB_BAU_SB_ACTIVATION_STATUS_0; + bcp->status_index = uvhub_cpu * UV_ACT_STATUS_SIZE; + } else { + bcp->status_mmr = UVH_LB_BAU_SB_ACTIVATION_STATUS_1; + bcp->status_index = (uvhub_cpu - UV_CPUS_PER_AS) + * UV_ACT_STATUS_SIZE; + } if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) { pr_emerg("%d cpus per uvhub invalid\n", @@ -2148,6 +2183,39 @@ fail: return 1; } +static const struct bau_operations uv1_bau_ops __initconst = { + .bau_gpa_to_offset = uv_gpa_to_offset, + .read_l_sw_ack = read_mmr_sw_ack, + .read_g_sw_ack = read_gmmr_sw_ack, + .write_l_sw_ack = write_mmr_sw_ack, + .write_g_sw_ack = write_gmmr_sw_ack, + .write_payload_first = write_mmr_payload_first, + .write_payload_last = write_mmr_payload_last, + .wait_completion = uv1_wait_completion, +}; + +static const struct bau_operations uv2_3_bau_ops __initconst = { + .bau_gpa_to_offset = uv_gpa_to_offset, + .read_l_sw_ack = read_mmr_sw_ack, + .read_g_sw_ack = read_gmmr_sw_ack, + .write_l_sw_ack = write_mmr_sw_ack, + .write_g_sw_ack = write_gmmr_sw_ack, + .write_payload_first = write_mmr_payload_first, + .write_payload_last = write_mmr_payload_last, + .wait_completion = uv2_3_wait_completion, +}; + +static const struct bau_operations uv4_bau_ops __initconst = { + .bau_gpa_to_offset = uv_gpa_to_soc_phys_ram, + .read_l_sw_ack = read_mmr_proc_sw_ack, + .read_g_sw_ack = read_gmmr_proc_sw_ack, + .write_l_sw_ack = write_mmr_proc_sw_ack, + .write_g_sw_ack = write_gmmr_proc_sw_ack, + .write_payload_first = write_mmr_proc_payload_first, + .write_payload_last = write_mmr_proc_payload_last, + .wait_completion = uv4_wait_completion, +}; + /* * Initialization of BAU-related structures */ @@ -2167,11 +2235,11 @@ static int __init uv_bau_init(void) if (is_uv4_hub()) ops = uv4_bau_ops; else if (is_uv3_hub()) - ops = uv123_bau_ops; + ops = uv2_3_bau_ops; else if (is_uv2_hub()) - ops = uv123_bau_ops; + ops = uv2_3_bau_ops; else if (is_uv1_hub()) - ops = uv123_bau_ops; + ops = uv1_bau_ops; for_each_possible_cpu(cur_cpu) { mask = &per_cpu(uv_flush_tlb_mask, cur_cpu); diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c index 2ee7632d4916..b082d71b08ee 100644 --- a/arch/x86/platform/uv/uv_time.c +++ b/arch/x86/platform/uv/uv_time.c @@ -390,9 +390,11 @@ static __init int uv_rtc_setup_clock(void) clock_event_device_uv.min_delta_ns = NSEC_PER_SEC / sn_rtc_cycles_per_second; + clock_event_device_uv.min_delta_ticks = 1; clock_event_device_uv.max_delta_ns = clocksource_uv.mask * (NSEC_PER_SEC / sn_rtc_cycles_per_second); + clock_event_device_uv.max_delta_ticks = clocksource_uv.mask; rc = schedule_on_each_cpu(uv_rtc_register_clockevents); if (rc) { diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 66ade16c7693..6b05a9219ea2 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -95,7 +95,7 @@ static void __save_processor_state(struct saved_context *ctxt) * 'pmode_gdt' in wakeup_start. */ ctxt->gdt_desc.size = GDT_SIZE - 1; - ctxt->gdt_desc.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); + ctxt->gdt_desc.address = (unsigned long)get_cpu_gdt_rw(smp_processor_id()); store_tr(ctxt->tr); @@ -162,7 +162,7 @@ static void fix_processor_context(void) int cpu = smp_processor_id(); struct tss_struct *t = &per_cpu(cpu_tss, cpu); #ifdef CONFIG_X86_64 - struct desc_struct *desc = get_cpu_gdt_table(cpu); + struct desc_struct *desc = get_cpu_gdt_rw(cpu); tss_desc tss; #endif set_tss_desc(cpu, t); /* @@ -183,6 +183,9 @@ static void fix_processor_context(void) load_mm_ldt(current->active_mm); /* This does lldt */ fpu__resume_cpu(); + + /* The processor is back on the direct GDT, load back the fixmap */ + load_fixmap_gdt(cpu); } /** diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index 9f14bd34581d..c35fdb585c68 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -32,6 +32,7 @@ pgd_t *resume_pg_dir; */ static pmd_t *resume_one_md_table_init(pgd_t *pgd) { + p4d_t *p4d; pud_t *pud; pmd_t *pmd_table; @@ -41,11 +42,13 @@ static pmd_t *resume_one_md_table_init(pgd_t *pgd) return NULL; set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); - pud = pud_offset(pgd, 0); + p4d = p4d_offset(pgd, 0); + pud = pud_offset(p4d, 0); BUG_ON(pmd_table != pmd_offset(pud, 0)); #else - pud = pud_offset(pgd, 0); + p4d = p4d_offset(pgd, 0); + pud = pud_offset(p4d, 0); pmd_table = pmd_offset(pud, 0); #endif diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index ded2e8272382..6a61194ffd58 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c @@ -16,6 +16,7 @@ #include <crypto/hash.h> +#include <asm/e820/api.h> #include <asm/init.h> #include <asm/proto.h> #include <asm/page.h> @@ -49,6 +50,7 @@ static int set_up_temporary_text_mapping(pgd_t *pgd) { pmd_t *pmd; pud_t *pud; + p4d_t *p4d; /* * The new mapping only has to cover the page containing the image @@ -63,6 +65,13 @@ static int set_up_temporary_text_mapping(pgd_t *pgd) * the virtual address space after switching over to the original page * tables used by the image kernel. */ + + if (IS_ENABLED(CONFIG_X86_5LEVEL)) { + p4d = (p4d_t *)get_safe_page(GFP_ATOMIC); + if (!p4d) + return -ENOMEM; + } + pud = (pud_t *)get_safe_page(GFP_ATOMIC); if (!pud) return -ENOMEM; @@ -75,8 +84,13 @@ static int set_up_temporary_text_mapping(pgd_t *pgd) __pmd((jump_address_phys & PMD_MASK) | __PAGE_KERNEL_LARGE_EXEC)); set_pud(pud + pud_index(restore_jump_address), __pud(__pa(pmd) | _KERNPG_TABLE)); - set_pgd(pgd + pgd_index(restore_jump_address), - __pgd(__pa(pud) | _KERNPG_TABLE)); + if (IS_ENABLED(CONFIG_X86_5LEVEL)) { + set_p4d(p4d + p4d_index(restore_jump_address), __p4d(__pa(pud) | _KERNPG_TABLE)); + set_pgd(pgd + pgd_index(restore_jump_address), __pgd(__pa(p4d) | _KERNPG_TABLE)); + } else { + /* No p4d for 4-level paging: point the pgd to the pud page table */ + set_pgd(pgd + pgd_index(restore_jump_address), __pgd(__pa(pud) | _KERNPG_TABLE)); + } return 0; } @@ -124,7 +138,10 @@ static int set_up_temporary_mappings(void) static int relocate_restore_code(void) { pgd_t *pgd; + p4d_t *p4d; pud_t *pud; + pmd_t *pmd; + pte_t *pte; relocated_restore_code = get_safe_page(GFP_ATOMIC); if (!relocated_restore_code) @@ -134,22 +151,25 @@ static int relocate_restore_code(void) /* Make the page containing the relocated code executable */ pgd = (pgd_t *)__va(read_cr3()) + pgd_index(relocated_restore_code); - pud = pud_offset(pgd, relocated_restore_code); + p4d = p4d_offset(pgd, relocated_restore_code); + if (p4d_large(*p4d)) { + set_p4d(p4d, __p4d(p4d_val(*p4d) & ~_PAGE_NX)); + goto out; + } + pud = pud_offset(p4d, relocated_restore_code); if (pud_large(*pud)) { set_pud(pud, __pud(pud_val(*pud) & ~_PAGE_NX)); - } else { - pmd_t *pmd = pmd_offset(pud, relocated_restore_code); - - if (pmd_large(*pmd)) { - set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_NX)); - } else { - pte_t *pte = pte_offset_kernel(pmd, relocated_restore_code); - - set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_NX)); - } + goto out; + } + pmd = pmd_offset(pud, relocated_restore_code); + if (pmd_large(*pmd)) { + set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_NX)); + goto out; } + pte = pte_offset_kernel(pmd, relocated_restore_code); + set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_NX)); +out: __flush_tlb_all(); - return 0; } @@ -195,12 +215,12 @@ struct restore_data_record { #if IS_BUILTIN(CONFIG_CRYPTO_MD5) /** - * get_e820_md5 - calculate md5 according to given e820 map + * get_e820_md5 - calculate md5 according to given e820 table * - * @map: the e820 map to be calculated + * @table: the e820 table to be calculated * @buf: the md5 result to be stored to */ -static int get_e820_md5(struct e820map *map, void *buf) +static int get_e820_md5(struct e820_table *table, void *buf) { struct scatterlist sg; struct crypto_ahash *tfm; @@ -213,10 +233,9 @@ static int get_e820_md5(struct e820map *map, void *buf) { AHASH_REQUEST_ON_STACK(req, tfm); - size = offsetof(struct e820map, map) - + sizeof(struct e820entry) * map->nr_map; + size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry) * table->nr_entries; ahash_request_set_tfm(req, tfm); - sg_init_one(&sg, (u8 *)map, size); + sg_init_one(&sg, (u8 *)table, size); ahash_request_set_callback(req, 0, NULL, NULL); ahash_request_set_crypt(req, &sg, buf, size); @@ -231,7 +250,7 @@ static int get_e820_md5(struct e820map *map, void *buf) static void hibernation_e820_save(void *buf) { - get_e820_md5(e820_saved, buf); + get_e820_md5(e820_table_firmware, buf); } static bool hibernation_e820_mismatch(void *buf) @@ -244,7 +263,7 @@ static bool hibernation_e820_mismatch(void *buf) if (!memcmp(result, buf, MD5_DIGEST_SIZE)) return false; - ret = get_e820_md5(e820_saved, result); + ret = get_e820_md5(e820_table_firmware, result); if (ret) return true; diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 555b9fa0ad43..7dbdb780264d 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -8,6 +8,7 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib targets += purgatory.ro +KASAN_SANITIZE := n KCOV_INSTRUMENT := n # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c index 25e068ba3382..470edad96bb9 100644 --- a/arch/x86/purgatory/purgatory.c +++ b/arch/x86/purgatory/purgatory.c @@ -10,21 +10,19 @@ * Version 2. See the file COPYING for more details. */ +#include <linux/bug.h> +#include <asm/purgatory.h> + #include "sha256.h" #include "../boot/string.h" -struct sha_region { - unsigned long start; - unsigned long len; -}; - -unsigned long backup_dest = 0; -unsigned long backup_src = 0; -unsigned long backup_sz = 0; +unsigned long purgatory_backup_dest __section(.kexec-purgatory); +unsigned long purgatory_backup_src __section(.kexec-purgatory); +unsigned long purgatory_backup_sz __section(.kexec-purgatory); -u8 sha256_digest[SHA256_DIGEST_SIZE] = { 0 }; +u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(.kexec-purgatory); -struct sha_region sha_regions[16] = {}; +struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(.kexec-purgatory); /* * On x86, second kernel requries first 640K of memory to boot. Copy @@ -33,26 +31,28 @@ struct sha_region sha_regions[16] = {}; */ static int copy_backup_region(void) { - if (backup_dest) - memcpy((void *)backup_dest, (void *)backup_src, backup_sz); - + if (purgatory_backup_dest) { + memcpy((void *)purgatory_backup_dest, + (void *)purgatory_backup_src, purgatory_backup_sz); + } return 0; } -int verify_sha256_digest(void) +static int verify_sha256_digest(void) { - struct sha_region *ptr, *end; + struct kexec_sha_region *ptr, *end; u8 digest[SHA256_DIGEST_SIZE]; struct sha256_state sctx; sha256_init(&sctx); - end = &sha_regions[sizeof(sha_regions)/sizeof(sha_regions[0])]; - for (ptr = sha_regions; ptr < end; ptr++) + end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); + + for (ptr = purgatory_sha_regions; ptr < end; ptr++) sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); sha256_final(&sctx, digest); - if (memcmp(digest, sha256_digest, sizeof(digest))) + if (memcmp(digest, purgatory_sha256_digest, sizeof(digest))) return 1; return 0; diff --git a/arch/x86/purgatory/setup-x86_64.S b/arch/x86/purgatory/setup-x86_64.S index fe3c91ba1bd0..dfae9b9e60b5 100644 --- a/arch/x86/purgatory/setup-x86_64.S +++ b/arch/x86/purgatory/setup-x86_64.S @@ -9,6 +9,7 @@ * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ +#include <asm/purgatory.h> .text .globl purgatory_start diff --git a/arch/x86/purgatory/sha256.h b/arch/x86/purgatory/sha256.h index bd15a4127735..2867d9825a57 100644 --- a/arch/x86/purgatory/sha256.h +++ b/arch/x86/purgatory/sha256.h @@ -10,7 +10,6 @@ #ifndef SHA256_H #define SHA256_H - #include <linux/types.h> #include <crypto/sha.h> diff --git a/arch/x86/ras/Kconfig b/arch/x86/ras/Kconfig index 0bc60a308730..2a2d89d39af6 100644 --- a/arch/x86/ras/Kconfig +++ b/arch/x86/ras/Kconfig @@ -7,3 +7,17 @@ config MCE_AMD_INJ aspects of the MCE handling code. WARNING: Do not even assume this interface is staying stable! + +config RAS_CEC + bool "Correctable Errors Collector" + depends on X86_MCE && MEMORY_FAILURE && DEBUG_FS + ---help--- + This is a small cache which collects correctable memory errors per 4K + page PFN and counts their repeated occurrence. Once the counter for a + PFN overflows, we try to soft-offline that page as we take it to mean + that it has reached a relatively high error count and would probably + be best if we don't use it anymore. + + Bear in mind that this is absolutely useless if your platform doesn't + have ECC DIMMs and doesn't have DRAM ECC checking enabled in the BIOS. + diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile index e7e7055a8658..46cbbfe03285 100644 --- a/arch/x86/um/Makefile +++ b/arch/x86/um/Makefile @@ -8,7 +8,7 @@ else BITS := 64 endif -obj-y = bug.o bugs_$(BITS).o delay.o fault.o ldt.o \ +obj-y = bugs_$(BITS).o delay.o fault.o ldt.o \ ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \ stub_$(BITS).o stub_segv.o \ sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \ @@ -16,7 +16,7 @@ obj-y = bug.o bugs_$(BITS).o delay.o fault.o ldt.o \ ifeq ($(CONFIG_X86_32),y) -obj-y += checksum_32.o +obj-y += checksum_32.o syscalls_32.o obj-$(CONFIG_ELF_CORE) += elfcore.o subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h index e59eef20647b..b291ca5cf66b 100644 --- a/arch/x86/um/asm/ptrace.h +++ b/arch/x86/um/asm/ptrace.h @@ -78,7 +78,7 @@ static inline int ptrace_set_thread_area(struct task_struct *child, int idx, return -ENOSYS; } -extern long arch_prctl(struct task_struct *task, int code, +extern long arch_prctl(struct task_struct *task, int option, unsigned long __user *addr); #endif diff --git a/arch/x86/um/bug.c b/arch/x86/um/bug.c deleted file mode 100644 index e8034e363d83..000000000000 --- a/arch/x86/um/bug.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL V2 - */ - -#include <linux/uaccess.h> - -/* - * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because - * that's not relevant in skas mode. - */ - -int is_valid_bugaddr(unsigned long eip) -{ - unsigned short ud2; - - if (probe_kernel_address((unsigned short __user *)eip, ud2)) - return 0; - - return ud2 == 0x0b0f; -} diff --git a/arch/x86/um/os-Linux/prctl.c b/arch/x86/um/os-Linux/prctl.c index 96eb2bd28832..8431e87ac333 100644 --- a/arch/x86/um/os-Linux/prctl.c +++ b/arch/x86/um/os-Linux/prctl.c @@ -6,7 +6,7 @@ #include <sys/ptrace.h> #include <asm/ptrace.h> -int os_arch_prctl(int pid, int code, unsigned long *addr) +int os_arch_prctl(int pid, int option, unsigned long *arg2) { - return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code); + return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) arg2, option); } diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c new file mode 100644 index 000000000000..627d68836b16 --- /dev/null +++ b/arch/x86/um/syscalls_32.c @@ -0,0 +1,7 @@ +#include <linux/syscalls.h> +#include <os.h> + +SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) +{ + return -EINVAL; +} diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c index 10d907098c26..58f51667e2e4 100644 --- a/arch/x86/um/syscalls_64.c +++ b/arch/x86/um/syscalls_64.c @@ -7,13 +7,15 @@ #include <linux/sched.h> #include <linux/sched/mm.h> +#include <linux/syscalls.h> #include <linux/uaccess.h> #include <asm/prctl.h> /* XXX This should get the constants from libc */ #include <os.h> -long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) +long arch_prctl(struct task_struct *task, int option, + unsigned long __user *arg2) { - unsigned long *ptr = addr, tmp; + unsigned long *ptr = arg2, tmp; long ret; int pid = task->mm->context.id.u.pid; @@ -30,7 +32,7 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) * arch_prctl is run on the host, then the registers are read * back. */ - switch (code) { + switch (option) { case ARCH_SET_FS: case ARCH_SET_GS: ret = restore_registers(pid, ¤t->thread.regs.regs); @@ -50,11 +52,11 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) ptr = &tmp; } - ret = os_arch_prctl(pid, code, ptr); + ret = os_arch_prctl(pid, option, ptr); if (ret) return ret; - switch (code) { + switch (option) { case ARCH_SET_FS: current->thread.arch.fs = (unsigned long) ptr; ret = save_registers(pid, ¤t->thread.regs.regs); @@ -63,19 +65,19 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: - ret = put_user(tmp, addr); + ret = put_user(tmp, arg2); break; case ARCH_GET_GS: - ret = put_user(tmp, addr); + ret = put_user(tmp, arg2); break; } return ret; } -long sys_arch_prctl(int code, unsigned long addr) +SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) { - return arch_prctl(current, code, (unsigned long __user *) addr); + return arch_prctl(current, option, (unsigned long __user *) arg2); } void arch_switch_to(struct task_struct *to) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index ec1d5c46e58f..30822e8e64ac 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -76,6 +76,7 @@ #include <asm/mwait.h> #include <asm/pci_x86.h> #include <asm/cpu.h> +#include <asm/e820/api.h> #ifdef CONFIG_ACPI #include <linux/acpi.h> @@ -710,7 +711,7 @@ static void load_TLS_descriptor(struct thread_struct *t, *shadow = t->tls_array[i]; - gdt = get_cpu_gdt_table(cpu); + gdt = get_cpu_gdt_rw(cpu); maddr = arbitrary_virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); mc = __xen_mc_entry(0); @@ -1595,7 +1596,6 @@ asmlinkage __visible void __init xen_start_kernel(void) /* set up basic CPUID stuff */ cpu_detect(&new_cpu_data); set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU); - new_cpu_data.wp_works_ok = 1; new_cpu_data.x86_capability[CPUID_1_EDX] = cpuid_edx(1); #endif @@ -1690,34 +1690,32 @@ static void __init init_pvh_bootparams(void) memset(&pvh_bootparams, 0, sizeof(pvh_bootparams)); - memmap.nr_entries = ARRAY_SIZE(pvh_bootparams.e820_map); - set_xen_guest_handle(memmap.buffer, pvh_bootparams.e820_map); + memmap.nr_entries = ARRAY_SIZE(pvh_bootparams.e820_table); + set_xen_guest_handle(memmap.buffer, pvh_bootparams.e820_table); rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); if (rc) { xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc); BUG(); } - if (memmap.nr_entries < E820MAX - 1) { - pvh_bootparams.e820_map[memmap.nr_entries].addr = + if (memmap.nr_entries < E820_MAX_ENTRIES_ZEROPAGE - 1) { + pvh_bootparams.e820_table[memmap.nr_entries].addr = ISA_START_ADDRESS; - pvh_bootparams.e820_map[memmap.nr_entries].size = + pvh_bootparams.e820_table[memmap.nr_entries].size = ISA_END_ADDRESS - ISA_START_ADDRESS; - pvh_bootparams.e820_map[memmap.nr_entries].type = - E820_RESERVED; + pvh_bootparams.e820_table[memmap.nr_entries].type = + E820_TYPE_RESERVED; memmap.nr_entries++; } else xen_raw_printk("Warning: Can fit ISA range into e820\n"); - sanitize_e820_map(pvh_bootparams.e820_map, - ARRAY_SIZE(pvh_bootparams.e820_map), - &memmap.nr_entries); - pvh_bootparams.e820_entries = memmap.nr_entries; for (i = 0; i < pvh_bootparams.e820_entries; i++) - e820_add_region(pvh_bootparams.e820_map[i].addr, - pvh_bootparams.e820_map[i].size, - pvh_bootparams.e820_map[i].type); + e820__range_add(pvh_bootparams.e820_table[i].addr, + pvh_bootparams.e820_table[i].size, + pvh_bootparams.e820_table[i].type); + + e820__update_table(e820_table); pvh_bootparams.hdr.cmd_line_ptr = pvh_start_info.cmdline_paddr; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 37cb5aad71de..f226038a39ca 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -58,7 +58,7 @@ #include <asm/mmu_context.h> #include <asm/setup.h> #include <asm/paravirt.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/linkage.h> #include <asm/page.h> #include <asm/init.h> @@ -535,40 +535,41 @@ static pgd_t *xen_get_user_pgd(pgd_t *pgd) return user_ptr; } -static void __xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) +static void __xen_set_p4d_hyper(p4d_t *ptr, p4d_t val) { struct mmu_update u; u.ptr = virt_to_machine(ptr).maddr; - u.val = pgd_val_ma(val); + u.val = p4d_val_ma(val); xen_extend_mmu_update(&u); } /* - * Raw hypercall-based set_pgd, intended for in early boot before + * Raw hypercall-based set_p4d, intended for in early boot before * there's a page structure. This implies: * 1. The only existing pagetable is the kernel's * 2. It is always pinned * 3. It has no user pagetable attached to it */ -static void __init xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) +static void __init xen_set_p4d_hyper(p4d_t *ptr, p4d_t val) { preempt_disable(); xen_mc_batch(); - __xen_set_pgd_hyper(ptr, val); + __xen_set_p4d_hyper(ptr, val); xen_mc_issue(PARAVIRT_LAZY_MMU); preempt_enable(); } -static void xen_set_pgd(pgd_t *ptr, pgd_t val) +static void xen_set_p4d(p4d_t *ptr, p4d_t val) { - pgd_t *user_ptr = xen_get_user_pgd(ptr); + pgd_t *user_ptr = xen_get_user_pgd((pgd_t *)ptr); + pgd_t pgd_val; - trace_xen_mmu_set_pgd(ptr, user_ptr, val); + trace_xen_mmu_set_p4d(ptr, (p4d_t *)user_ptr, val); /* If page is not pinned, we can just update the entry directly */ @@ -576,7 +577,8 @@ static void xen_set_pgd(pgd_t *ptr, pgd_t val) *ptr = val; if (user_ptr) { WARN_ON(xen_page_pinned(user_ptr)); - *user_ptr = val; + pgd_val.pgd = p4d_val_ma(val); + *user_ptr = pgd_val; } return; } @@ -585,14 +587,72 @@ static void xen_set_pgd(pgd_t *ptr, pgd_t val) user updates together. */ xen_mc_batch(); - __xen_set_pgd_hyper(ptr, val); + __xen_set_p4d_hyper(ptr, val); if (user_ptr) - __xen_set_pgd_hyper(user_ptr, val); + __xen_set_p4d_hyper((p4d_t *)user_ptr, val); xen_mc_issue(PARAVIRT_LAZY_MMU); } #endif /* CONFIG_PGTABLE_LEVELS == 4 */ +static int xen_pmd_walk(struct mm_struct *mm, pmd_t *pmd, + int (*func)(struct mm_struct *mm, struct page *, enum pt_level), + bool last, unsigned long limit) +{ + int i, nr, flush = 0; + + nr = last ? pmd_index(limit) + 1 : PTRS_PER_PMD; + for (i = 0; i < nr; i++) { + if (!pmd_none(pmd[i])) + flush |= (*func)(mm, pmd_page(pmd[i]), PT_PTE); + } + return flush; +} + +static int xen_pud_walk(struct mm_struct *mm, pud_t *pud, + int (*func)(struct mm_struct *mm, struct page *, enum pt_level), + bool last, unsigned long limit) +{ + int i, nr, flush = 0; + + nr = last ? pud_index(limit) + 1 : PTRS_PER_PUD; + for (i = 0; i < nr; i++) { + pmd_t *pmd; + + if (pud_none(pud[i])) + continue; + + pmd = pmd_offset(&pud[i], 0); + if (PTRS_PER_PMD > 1) + flush |= (*func)(mm, virt_to_page(pmd), PT_PMD); + flush |= xen_pmd_walk(mm, pmd, func, + last && i == nr - 1, limit); + } + return flush; +} + +static int xen_p4d_walk(struct mm_struct *mm, p4d_t *p4d, + int (*func)(struct mm_struct *mm, struct page *, enum pt_level), + bool last, unsigned long limit) +{ + int i, nr, flush = 0; + + nr = last ? p4d_index(limit) + 1 : PTRS_PER_P4D; + for (i = 0; i < nr; i++) { + pud_t *pud; + + if (p4d_none(p4d[i])) + continue; + + pud = pud_offset(&p4d[i], 0); + if (PTRS_PER_PUD > 1) + flush |= (*func)(mm, virt_to_page(pud), PT_PUD); + flush |= xen_pud_walk(mm, pud, func, + last && i == nr - 1, limit); + } + return flush; +} + /* * (Yet another) pagetable walker. This one is intended for pinning a * pagetable. This means that it walks a pagetable and calls the @@ -613,10 +673,8 @@ static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd, enum pt_level), unsigned long limit) { - int flush = 0; + int i, nr, flush = 0; unsigned hole_low, hole_high; - unsigned pgdidx_limit, pudidx_limit, pmdidx_limit; - unsigned pgdidx, pudidx, pmdidx; /* The limit is the last byte to be touched */ limit--; @@ -633,65 +691,22 @@ static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd, hole_low = pgd_index(USER_LIMIT); hole_high = pgd_index(PAGE_OFFSET); - pgdidx_limit = pgd_index(limit); -#if PTRS_PER_PUD > 1 - pudidx_limit = pud_index(limit); -#else - pudidx_limit = 0; -#endif -#if PTRS_PER_PMD > 1 - pmdidx_limit = pmd_index(limit); -#else - pmdidx_limit = 0; -#endif - - for (pgdidx = 0; pgdidx <= pgdidx_limit; pgdidx++) { - pud_t *pud; + nr = pgd_index(limit) + 1; + for (i = 0; i < nr; i++) { + p4d_t *p4d; - if (pgdidx >= hole_low && pgdidx < hole_high) + if (i >= hole_low && i < hole_high) continue; - if (!pgd_val(pgd[pgdidx])) + if (pgd_none(pgd[i])) continue; - pud = pud_offset(&pgd[pgdidx], 0); - - if (PTRS_PER_PUD > 1) /* not folded */ - flush |= (*func)(mm, virt_to_page(pud), PT_PUD); - - for (pudidx = 0; pudidx < PTRS_PER_PUD; pudidx++) { - pmd_t *pmd; - - if (pgdidx == pgdidx_limit && - pudidx > pudidx_limit) - goto out; - - if (pud_none(pud[pudidx])) - continue; - - pmd = pmd_offset(&pud[pudidx], 0); - - if (PTRS_PER_PMD > 1) /* not folded */ - flush |= (*func)(mm, virt_to_page(pmd), PT_PMD); - - for (pmdidx = 0; pmdidx < PTRS_PER_PMD; pmdidx++) { - struct page *pte; - - if (pgdidx == pgdidx_limit && - pudidx == pudidx_limit && - pmdidx > pmdidx_limit) - goto out; - - if (pmd_none(pmd[pmdidx])) - continue; - - pte = pmd_page(pmd[pmdidx]); - flush |= (*func)(mm, pte, PT_PTE); - } - } + p4d = p4d_offset(&pgd[i], 0); + if (PTRS_PER_P4D > 1) + flush |= (*func)(mm, virt_to_page(p4d), PT_P4D); + flush |= xen_p4d_walk(mm, p4d, func, i == nr - 1, limit); } -out: /* Do the top level last, so that the callbacks can use it as a cue to do final things like tlb flushes. */ flush |= (*func)(mm, virt_to_page(pgd), PT_PGD); @@ -1150,57 +1165,97 @@ static void __init xen_cleanmfnmap_free_pgtbl(void *pgtbl, bool unpin) xen_free_ro_pages(pa, PAGE_SIZE); } +static void __init xen_cleanmfnmap_pmd(pmd_t *pmd, bool unpin) +{ + unsigned long pa; + pte_t *pte_tbl; + int i; + + if (pmd_large(*pmd)) { + pa = pmd_val(*pmd) & PHYSICAL_PAGE_MASK; + xen_free_ro_pages(pa, PMD_SIZE); + return; + } + + pte_tbl = pte_offset_kernel(pmd, 0); + for (i = 0; i < PTRS_PER_PTE; i++) { + if (pte_none(pte_tbl[i])) + continue; + pa = pte_pfn(pte_tbl[i]) << PAGE_SHIFT; + xen_free_ro_pages(pa, PAGE_SIZE); + } + set_pmd(pmd, __pmd(0)); + xen_cleanmfnmap_free_pgtbl(pte_tbl, unpin); +} + +static void __init xen_cleanmfnmap_pud(pud_t *pud, bool unpin) +{ + unsigned long pa; + pmd_t *pmd_tbl; + int i; + + if (pud_large(*pud)) { + pa = pud_val(*pud) & PHYSICAL_PAGE_MASK; + xen_free_ro_pages(pa, PUD_SIZE); + return; + } + + pmd_tbl = pmd_offset(pud, 0); + for (i = 0; i < PTRS_PER_PMD; i++) { + if (pmd_none(pmd_tbl[i])) + continue; + xen_cleanmfnmap_pmd(pmd_tbl + i, unpin); + } + set_pud(pud, __pud(0)); + xen_cleanmfnmap_free_pgtbl(pmd_tbl, unpin); +} + +static void __init xen_cleanmfnmap_p4d(p4d_t *p4d, bool unpin) +{ + unsigned long pa; + pud_t *pud_tbl; + int i; + + if (p4d_large(*p4d)) { + pa = p4d_val(*p4d) & PHYSICAL_PAGE_MASK; + xen_free_ro_pages(pa, P4D_SIZE); + return; + } + + pud_tbl = pud_offset(p4d, 0); + for (i = 0; i < PTRS_PER_PUD; i++) { + if (pud_none(pud_tbl[i])) + continue; + xen_cleanmfnmap_pud(pud_tbl + i, unpin); + } + set_p4d(p4d, __p4d(0)); + xen_cleanmfnmap_free_pgtbl(pud_tbl, unpin); +} + /* * Since it is well isolated we can (and since it is perhaps large we should) * also free the page tables mapping the initial P->M table. */ static void __init xen_cleanmfnmap(unsigned long vaddr) { - unsigned long va = vaddr & PMD_MASK; - unsigned long pa; - pgd_t *pgd = pgd_offset_k(va); - pud_t *pud_page = pud_offset(pgd, 0); - pud_t *pud; - pmd_t *pmd; - pte_t *pte; + pgd_t *pgd; + p4d_t *p4d; unsigned int i; bool unpin; unpin = (vaddr == 2 * PGDIR_SIZE); - set_pgd(pgd, __pgd(0)); - do { - pud = pud_page + pud_index(va); - if (pud_none(*pud)) { - va += PUD_SIZE; - } else if (pud_large(*pud)) { - pa = pud_val(*pud) & PHYSICAL_PAGE_MASK; - xen_free_ro_pages(pa, PUD_SIZE); - va += PUD_SIZE; - } else { - pmd = pmd_offset(pud, va); - if (pmd_large(*pmd)) { - pa = pmd_val(*pmd) & PHYSICAL_PAGE_MASK; - xen_free_ro_pages(pa, PMD_SIZE); - } else if (!pmd_none(*pmd)) { - pte = pte_offset_kernel(pmd, va); - set_pmd(pmd, __pmd(0)); - for (i = 0; i < PTRS_PER_PTE; ++i) { - if (pte_none(pte[i])) - break; - pa = pte_pfn(pte[i]) << PAGE_SHIFT; - xen_free_ro_pages(pa, PAGE_SIZE); - } - xen_cleanmfnmap_free_pgtbl(pte, unpin); - } - va += PMD_SIZE; - if (pmd_index(va)) - continue; - set_pud(pud, __pud(0)); - xen_cleanmfnmap_free_pgtbl(pmd, unpin); - } - - } while (pud_index(va) || pmd_index(va)); - xen_cleanmfnmap_free_pgtbl(pud_page, unpin); + vaddr &= PMD_MASK; + pgd = pgd_offset_k(vaddr); + p4d = p4d_offset(pgd, 0); + for (i = 0; i < PTRS_PER_P4D; i++) { + if (p4d_none(p4d[i])) + continue; + xen_cleanmfnmap_p4d(p4d + i, unpin); + } + if (IS_ENABLED(CONFIG_X86_5LEVEL)) { + set_pgd(pgd, __pgd(0)); + xen_cleanmfnmap_free_pgtbl(p4d, unpin); + } } static void __init xen_pagetable_p2m_free(void) @@ -1538,7 +1593,6 @@ static int xen_pgd_alloc(struct mm_struct *mm) BUG_ON(PagePinned(virt_to_page(xen_get_user_pgd(pgd)))); } #endif - return ret; } @@ -1730,7 +1784,7 @@ static void xen_release_pmd(unsigned long pfn) xen_release_ptpage(pfn, PT_PMD); } -#if CONFIG_PGTABLE_LEVELS == 4 +#if CONFIG_PGTABLE_LEVELS >= 4 static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PUD); @@ -2071,21 +2125,27 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) */ void __init xen_relocate_p2m(void) { - phys_addr_t size, new_area, pt_phys, pmd_phys, pud_phys; + phys_addr_t size, new_area, pt_phys, pmd_phys, pud_phys, p4d_phys; unsigned long p2m_pfn, p2m_pfn_end, n_frames, pfn, pfn_end; - int n_pte, n_pt, n_pmd, n_pud, idx_pte, idx_pt, idx_pmd, idx_pud; + int n_pte, n_pt, n_pmd, n_pud, n_p4d, idx_pte, idx_pt, idx_pmd, idx_pud, idx_p4d; pte_t *pt; pmd_t *pmd; pud_t *pud; + p4d_t *p4d = NULL; pgd_t *pgd; unsigned long *new_p2m; + int save_pud; size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long)); n_pte = roundup(size, PAGE_SIZE) >> PAGE_SHIFT; n_pt = roundup(size, PMD_SIZE) >> PMD_SHIFT; n_pmd = roundup(size, PUD_SIZE) >> PUD_SHIFT; - n_pud = roundup(size, PGDIR_SIZE) >> PGDIR_SHIFT; - n_frames = n_pte + n_pt + n_pmd + n_pud; + n_pud = roundup(size, P4D_SIZE) >> P4D_SHIFT; + if (PTRS_PER_P4D > 1) + n_p4d = roundup(size, PGDIR_SIZE) >> PGDIR_SHIFT; + else + n_p4d = 0; + n_frames = n_pte + n_pt + n_pmd + n_pud + n_p4d; new_area = xen_find_free_area(PFN_PHYS(n_frames)); if (!new_area) { @@ -2101,55 +2161,76 @@ void __init xen_relocate_p2m(void) * To avoid any possible virtual address collision, just use * 2 * PUD_SIZE for the new area. */ - pud_phys = new_area; + p4d_phys = new_area; + pud_phys = p4d_phys + PFN_PHYS(n_p4d); pmd_phys = pud_phys + PFN_PHYS(n_pud); pt_phys = pmd_phys + PFN_PHYS(n_pmd); p2m_pfn = PFN_DOWN(pt_phys) + n_pt; pgd = __va(read_cr3()); new_p2m = (unsigned long *)(2 * PGDIR_SIZE); - for (idx_pud = 0; idx_pud < n_pud; idx_pud++) { - pud = early_memremap(pud_phys, PAGE_SIZE); - clear_page(pud); - for (idx_pmd = 0; idx_pmd < min(n_pmd, PTRS_PER_PUD); - idx_pmd++) { - pmd = early_memremap(pmd_phys, PAGE_SIZE); - clear_page(pmd); - for (idx_pt = 0; idx_pt < min(n_pt, PTRS_PER_PMD); - idx_pt++) { - pt = early_memremap(pt_phys, PAGE_SIZE); - clear_page(pt); - for (idx_pte = 0; - idx_pte < min(n_pte, PTRS_PER_PTE); - idx_pte++) { - set_pte(pt + idx_pte, - pfn_pte(p2m_pfn, PAGE_KERNEL)); - p2m_pfn++; + idx_p4d = 0; + save_pud = n_pud; + do { + if (n_p4d > 0) { + p4d = early_memremap(p4d_phys, PAGE_SIZE); + clear_page(p4d); + n_pud = min(save_pud, PTRS_PER_P4D); + } + for (idx_pud = 0; idx_pud < n_pud; idx_pud++) { + pud = early_memremap(pud_phys, PAGE_SIZE); + clear_page(pud); + for (idx_pmd = 0; idx_pmd < min(n_pmd, PTRS_PER_PUD); + idx_pmd++) { + pmd = early_memremap(pmd_phys, PAGE_SIZE); + clear_page(pmd); + for (idx_pt = 0; idx_pt < min(n_pt, PTRS_PER_PMD); + idx_pt++) { + pt = early_memremap(pt_phys, PAGE_SIZE); + clear_page(pt); + for (idx_pte = 0; + idx_pte < min(n_pte, PTRS_PER_PTE); + idx_pte++) { + set_pte(pt + idx_pte, + pfn_pte(p2m_pfn, PAGE_KERNEL)); + p2m_pfn++; + } + n_pte -= PTRS_PER_PTE; + early_memunmap(pt, PAGE_SIZE); + make_lowmem_page_readonly(__va(pt_phys)); + pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, + PFN_DOWN(pt_phys)); + set_pmd(pmd + idx_pt, + __pmd(_PAGE_TABLE | pt_phys)); + pt_phys += PAGE_SIZE; } - n_pte -= PTRS_PER_PTE; - early_memunmap(pt, PAGE_SIZE); - make_lowmem_page_readonly(__va(pt_phys)); - pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, - PFN_DOWN(pt_phys)); - set_pmd(pmd + idx_pt, - __pmd(_PAGE_TABLE | pt_phys)); - pt_phys += PAGE_SIZE; + n_pt -= PTRS_PER_PMD; + early_memunmap(pmd, PAGE_SIZE); + make_lowmem_page_readonly(__va(pmd_phys)); + pin_pagetable_pfn(MMUEXT_PIN_L2_TABLE, + PFN_DOWN(pmd_phys)); + set_pud(pud + idx_pmd, __pud(_PAGE_TABLE | pmd_phys)); + pmd_phys += PAGE_SIZE; } - n_pt -= PTRS_PER_PMD; - early_memunmap(pmd, PAGE_SIZE); - make_lowmem_page_readonly(__va(pmd_phys)); - pin_pagetable_pfn(MMUEXT_PIN_L2_TABLE, - PFN_DOWN(pmd_phys)); - set_pud(pud + idx_pmd, __pud(_PAGE_TABLE | pmd_phys)); - pmd_phys += PAGE_SIZE; + n_pmd -= PTRS_PER_PUD; + early_memunmap(pud, PAGE_SIZE); + make_lowmem_page_readonly(__va(pud_phys)); + pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(pud_phys)); + if (n_p4d > 0) + set_p4d(p4d + idx_pud, __p4d(_PAGE_TABLE | pud_phys)); + else + set_pgd(pgd + 2 + idx_pud, __pgd(_PAGE_TABLE | pud_phys)); + pud_phys += PAGE_SIZE; } - n_pmd -= PTRS_PER_PUD; - early_memunmap(pud, PAGE_SIZE); - make_lowmem_page_readonly(__va(pud_phys)); - pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(pud_phys)); - set_pgd(pgd + 2 + idx_pud, __pgd(_PAGE_TABLE | pud_phys)); - pud_phys += PAGE_SIZE; - } + if (n_p4d > 0) { + save_pud -= PTRS_PER_P4D; + early_memunmap(p4d, PAGE_SIZE); + make_lowmem_page_readonly(__va(p4d_phys)); + pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, PFN_DOWN(p4d_phys)); + set_pgd(pgd + 2 + idx_p4d, __pgd(_PAGE_TABLE | p4d_phys)); + p4d_phys += PAGE_SIZE; + } + } while (++idx_p4d < n_p4d); /* Now copy the old p2m info to the new area. */ memcpy(new_p2m, xen_p2m_addr, size); @@ -2326,6 +2407,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) #endif case FIX_TEXT_POKE0: case FIX_TEXT_POKE1: + case FIX_GDT_REMAP_BEGIN ... FIX_GDT_REMAP_END: /* All local page mappings */ pte = pfn_pte(phys, prot); break; @@ -2378,8 +2460,8 @@ static void __init xen_post_allocator_init(void) pv_mmu_ops.set_pte = xen_set_pte; pv_mmu_ops.set_pmd = xen_set_pmd; pv_mmu_ops.set_pud = xen_set_pud; -#if CONFIG_PGTABLE_LEVELS == 4 - pv_mmu_ops.set_pgd = xen_set_pgd; +#if CONFIG_PGTABLE_LEVELS >= 4 + pv_mmu_ops.set_p4d = xen_set_p4d; #endif /* This will work as long as patching hasn't happened yet @@ -2388,7 +2470,7 @@ static void __init xen_post_allocator_init(void) pv_mmu_ops.alloc_pmd = xen_alloc_pmd; pv_mmu_ops.release_pte = xen_release_pte; pv_mmu_ops.release_pmd = xen_release_pmd; -#if CONFIG_PGTABLE_LEVELS == 4 +#if CONFIG_PGTABLE_LEVELS >= 4 pv_mmu_ops.alloc_pud = xen_alloc_pud; pv_mmu_ops.release_pud = xen_release_pud; #endif @@ -2454,10 +2536,10 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { .make_pmd = PV_CALLEE_SAVE(xen_make_pmd), .pmd_val = PV_CALLEE_SAVE(xen_pmd_val), -#if CONFIG_PGTABLE_LEVELS == 4 +#if CONFIG_PGTABLE_LEVELS >= 4 .pud_val = PV_CALLEE_SAVE(xen_pud_val), .make_pud = PV_CALLEE_SAVE(xen_make_pud), - .set_pgd = xen_set_pgd_hyper, + .set_p4d = xen_set_p4d_hyper, .alloc_pud = xen_alloc_pmd_init, .release_pud = xen_release_pmd_init, diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 73809bb951b4..3fe2b3292915 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -5,6 +5,7 @@ enum pt_level { PT_PGD, + PT_P4D, PT_PUD, PT_PMD, PT_PTE diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index a8c306cf8868..a5bf7c451435 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -14,7 +14,7 @@ #include <asm/elf.h> #include <asm/vdso.h> -#include <asm/e820.h> +#include <asm/e820/api.h> #include <asm/setup.h> #include <asm/acpi.h> #include <asm/numa.h> @@ -41,8 +41,7 @@ struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata; unsigned long xen_released_pages; /* E820 map used during setting up memory. */ -static struct e820entry xen_e820_map[E820_X_MAX] __initdata; -static u32 xen_e820_map_entries __initdata; +static struct e820_table xen_e820_table __initdata; /* * Buffer used to remap identity mapped pages. We only need the virtual space. @@ -198,15 +197,15 @@ void __init xen_inv_extra_mem(void) */ static unsigned long __init xen_find_pfn_range(unsigned long *min_pfn) { - const struct e820entry *entry = xen_e820_map; + const struct e820_entry *entry = xen_e820_table.entries; unsigned int i; unsigned long done = 0; - for (i = 0; i < xen_e820_map_entries; i++, entry++) { + for (i = 0; i < xen_e820_table.nr_entries; i++, entry++) { unsigned long s_pfn; unsigned long e_pfn; - if (entry->type != E820_RAM) + if (entry->type != E820_TYPE_RAM) continue; e_pfn = PFN_DOWN(entry->addr + entry->size); @@ -457,7 +456,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, { phys_addr_t start = 0; unsigned long ret_val = 0; - const struct e820entry *entry = xen_e820_map; + const struct e820_entry *entry = xen_e820_table.entries; int i; /* @@ -471,13 +470,13 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, * example) the DMI tables in a reserved region that begins on * a non-page boundary. */ - for (i = 0; i < xen_e820_map_entries; i++, entry++) { + for (i = 0; i < xen_e820_table.nr_entries; i++, entry++) { phys_addr_t end = entry->addr + entry->size; - if (entry->type == E820_RAM || i == xen_e820_map_entries - 1) { + if (entry->type == E820_TYPE_RAM || i == xen_e820_table.nr_entries - 1) { unsigned long start_pfn = PFN_DOWN(start); unsigned long end_pfn = PFN_UP(end); - if (entry->type == E820_RAM) + if (entry->type == E820_TYPE_RAM) end_pfn = PFN_UP(entry->addr); if (start_pfn < end_pfn) @@ -591,28 +590,28 @@ static void __init xen_align_and_add_e820_region(phys_addr_t start, phys_addr_t end = start + size; /* Align RAM regions to page boundaries. */ - if (type == E820_RAM) { + if (type == E820_TYPE_RAM) { start = PAGE_ALIGN(start); end &= ~((phys_addr_t)PAGE_SIZE - 1); } - e820_add_region(start, end - start, type); + e820__range_add(start, end - start, type); } static void __init xen_ignore_unusable(void) { - struct e820entry *entry = xen_e820_map; + struct e820_entry *entry = xen_e820_table.entries; unsigned int i; - for (i = 0; i < xen_e820_map_entries; i++, entry++) { - if (entry->type == E820_UNUSABLE) - entry->type = E820_RAM; + for (i = 0; i < xen_e820_table.nr_entries; i++, entry++) { + if (entry->type == E820_TYPE_UNUSABLE) + entry->type = E820_TYPE_RAM; } } bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) { - struct e820entry *entry; + struct e820_entry *entry; unsigned mapcnt; phys_addr_t end; @@ -620,10 +619,10 @@ bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) return false; end = start + size; - entry = xen_e820_map; + entry = xen_e820_table.entries; - for (mapcnt = 0; mapcnt < xen_e820_map_entries; mapcnt++) { - if (entry->type == E820_RAM && entry->addr <= start && + for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) { + if (entry->type == E820_TYPE_RAM && entry->addr <= start && (entry->addr + entry->size) >= end) return false; @@ -645,10 +644,10 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size) { unsigned mapcnt; phys_addr_t addr, start; - struct e820entry *entry = xen_e820_map; + struct e820_entry *entry = xen_e820_table.entries; - for (mapcnt = 0; mapcnt < xen_e820_map_entries; mapcnt++, entry++) { - if (entry->type != E820_RAM || entry->size < size) + for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++, entry++) { + if (entry->type != E820_TYPE_RAM || entry->size < size) continue; start = entry->addr; for (addr = start; addr < start + size; addr += PAGE_SIZE) { @@ -750,8 +749,8 @@ char * __init xen_memory_setup(void) max_pfn = min(max_pfn, xen_start_info->nr_pages); mem_end = PFN_PHYS(max_pfn); - memmap.nr_entries = ARRAY_SIZE(xen_e820_map); - set_xen_guest_handle(memmap.buffer, xen_e820_map); + memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries); + set_xen_guest_handle(memmap.buffer, xen_e820_table.entries); op = xen_initial_domain() ? XENMEM_machine_memory_map : @@ -760,16 +759,16 @@ char * __init xen_memory_setup(void) if (rc == -ENOSYS) { BUG_ON(xen_initial_domain()); memmap.nr_entries = 1; - xen_e820_map[0].addr = 0ULL; - xen_e820_map[0].size = mem_end; + xen_e820_table.entries[0].addr = 0ULL; + xen_e820_table.entries[0].size = mem_end; /* 8MB slack (to balance backend allocations). */ - xen_e820_map[0].size += 8ULL << 20; - xen_e820_map[0].type = E820_RAM; + xen_e820_table.entries[0].size += 8ULL << 20; + xen_e820_table.entries[0].type = E820_TYPE_RAM; rc = 0; } BUG_ON(rc); BUG_ON(memmap.nr_entries == 0); - xen_e820_map_entries = memmap.nr_entries; + xen_e820_table.nr_entries = memmap.nr_entries; /* * Xen won't allow a 1:1 mapping to be created to UNUSABLE @@ -783,8 +782,7 @@ char * __init xen_memory_setup(void) xen_ignore_unusable(); /* Make sure the Xen-supplied memory map is well-ordered. */ - sanitize_e820_map(xen_e820_map, ARRAY_SIZE(xen_e820_map), - &xen_e820_map_entries); + e820__update_table(&xen_e820_table); max_pages = xen_get_max_pages(); @@ -811,15 +809,15 @@ char * __init xen_memory_setup(void) extra_pages = min3(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)), extra_pages, max_pages - max_pfn); i = 0; - addr = xen_e820_map[0].addr; - size = xen_e820_map[0].size; - while (i < xen_e820_map_entries) { + addr = xen_e820_table.entries[0].addr; + size = xen_e820_table.entries[0].size; + while (i < xen_e820_table.nr_entries) { bool discard = false; chunk_size = size; - type = xen_e820_map[i].type; + type = xen_e820_table.entries[i].type; - if (type == E820_RAM) { + if (type == E820_TYPE_RAM) { if (addr < mem_end) { chunk_size = min(size, mem_end - addr); } else if (extra_pages) { @@ -840,9 +838,9 @@ char * __init xen_memory_setup(void) size -= chunk_size; if (size == 0) { i++; - if (i < xen_e820_map_entries) { - addr = xen_e820_map[i].addr; - size = xen_e820_map[i].size; + if (i < xen_e820_table.nr_entries) { + addr = xen_e820_table.entries[i].addr; + size = xen_e820_table.entries[i].size; } } } @@ -858,10 +856,9 @@ char * __init xen_memory_setup(void) * reserve ISA memory anyway because too many things poke * about in there. */ - e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS, - E820_RESERVED); + e820__range_add(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS, E820_TYPE_RESERVED); - sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map); + e820__update_table(e820_table); /* * Check whether the kernel itself conflicts with the target E820 map. @@ -915,6 +912,37 @@ char * __init xen_memory_setup(void) } /* + * Machine specific memory setup for auto-translated guests. + */ +char * __init xen_auto_xlated_memory_setup(void) +{ + struct xen_memory_map memmap; + int i; + int rc; + + memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries); + set_xen_guest_handle(memmap.buffer, xen_e820_table.entries); + + rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); + if (rc < 0) + panic("No memory map (%d)\n", rc); + + xen_e820_table.nr_entries = memmap.nr_entries; + + e820__update_table(&xen_e820_table); + + for (i = 0; i < xen_e820_table.nr_entries; i++) + e820__range_add(xen_e820_table.entries[i].addr, xen_e820_table.entries[i].size, xen_e820_table.entries[i].type); + + /* Remove p2m info, it is not needed. */ + xen_start_info->mfn_list = 0; + xen_start_info->first_p2m_pfn = 0; + xen_start_info->nr_p2m_frames = 0; + + return "Xen"; +} + +/* * Set the bit indicating "nosegneg" library variants should be used. * We only need to bother in pure 32-bit mode; compat 32-bit processes * can have un-truncated segments, so wrapping around is allowed. @@ -999,8 +1027,8 @@ void __init xen_pvmmu_arch_setup(void) void __init xen_arch_setup(void) { xen_panic_handler_init(); - - xen_pvmmu_arch_setup(); + if (!xen_feature(XENFEAT_auto_translated_physmap)) + xen_pvmmu_arch_setup(); #ifdef CONFIG_ACPI if (!(xen_start_info->flags & SIF_INITDOMAIN)) { diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 7ff2f1bfb7ec..eaa36162ed4a 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -392,7 +392,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) if (ctxt == NULL) return -ENOMEM; - gdt = get_cpu_gdt_table(cpu); + gdt = get_cpu_gdt_rw(cpu); #ifdef CONFIG_X86_32 ctxt->user_regs.fs = __KERNEL_PERCPU; diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 1e69956d7852..7a3089285c59 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -209,7 +209,9 @@ static const struct clock_event_device xen_timerop_clockevent = { .features = CLOCK_EVT_FEAT_ONESHOT, .max_delta_ns = 0xffffffff, + .max_delta_ticks = 0xffffffff, .min_delta_ns = TIMER_SLOP, + .min_delta_ticks = TIMER_SLOP, .mult = 1, .shift = 0, @@ -268,7 +270,9 @@ static const struct clock_event_device xen_vcpuop_clockevent = { .features = CLOCK_EVT_FEAT_ONESHOT, .max_delta_ns = 0xffffffff, + .max_delta_ticks = 0xffffffff, .min_delta_ns = TIMER_SLOP, + .min_delta_ticks = TIMER_SLOP, .mult = 1, .shift = 0, diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index f41408c53fe1..cc23e9ecc6bb 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -6,6 +6,7 @@ generic-y += dma-contiguous.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fcntl.h generic-y += hardirq.h generic-y += ioctl.h diff --git a/arch/xtensa/include/asm/asm-uaccess.h b/arch/xtensa/include/asm/asm-uaccess.h index a7a110039786..dfdf9fae1f84 100644 --- a/arch/xtensa/include/asm/asm-uaccess.h +++ b/arch/xtensa/include/asm/asm-uaccess.h @@ -19,9 +19,6 @@ #include <linux/errno.h> #include <asm/types.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #include <asm/current.h> #include <asm/asm-offsets.h> #include <asm/processor.h> diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 976b1d70edbc..4ddbfd57a7c8 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h @@ -164,8 +164,21 @@ void copy_user_highpage(struct page *to, struct page *from, #define ARCH_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) +#ifdef CONFIG_MMU +static inline unsigned long ___pa(unsigned long va) +{ + unsigned long off = va - PAGE_OFFSET; + + if (off >= XCHAL_KSEG_SIZE) + off -= XCHAL_KSEG_SIZE; + + return off + PHYS_OFFSET; +} +#define __pa(x) ___pa((unsigned long)(x)) +#else #define __pa(x) \ ((unsigned long) (x) - PAGE_OFFSET + PHYS_OFFSET) +#endif #define __va(x) \ ((void *)((unsigned long) (x) - PHYS_OFFSET + PAGE_OFFSET)) #define pfn_valid(pfn) \ diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 8aa0e0d9cbb2..30dd5b2e4ad5 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -11,6 +11,7 @@ #ifndef _XTENSA_PGTABLE_H #define _XTENSA_PGTABLE_H +#define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #include <asm/page.h> #include <asm/kmem_layout.h> diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 848a3d736bcb..2e7bac0d4b2c 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -16,14 +16,9 @@ #ifndef _XTENSA_UACCESS_H #define _XTENSA_UACCESS_H -#include <linux/errno.h> #include <linux/prefetch.h> #include <asm/types.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -#include <linux/sched.h> +#include <asm/extable.h> /* * The fs value determines whether argument validity checking should @@ -43,7 +38,7 @@ #define segment_eq(a, b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) +#define __kernel_ok (uaccess_kernel()) #define __user_ok(addr, size) \ (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) #define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) @@ -239,60 +234,22 @@ __asm__ __volatile__( \ * Copy to/from user space */ -/* - * We use a generic, arbitrary-sized copy subroutine. The Xtensa - * architecture would cause heavy code bloat if we tried to inline - * these functions and provide __constant_copy_* equivalents like the - * i386 versions. __xtensa_copy_user is quite efficient. See the - * .fixup section of __xtensa_copy_user for a discussion on the - * X_zeroing equivalents for Xtensa. - */ - extern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n); -#define __copy_user(to, from, size) __xtensa_copy_user(to, from, size) - static inline unsigned long -__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - return __copy_user(to, from, n); -} - -static inline unsigned long -__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) -{ - return __copy_user(to, from, n); + prefetchw(to); + return __xtensa_copy_user(to, (__force const void *)from, n); } - static inline unsigned long -__generic_copy_to_user(void *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { prefetch(from); - if (access_ok(VERIFY_WRITE, to, n)) - return __copy_user(to, from, n); - return n; -} - -static inline unsigned long -__generic_copy_from_user(void *to, const void *from, unsigned long n) -{ - prefetchw(to); - if (access_ok(VERIFY_READ, from, n)) - return __copy_user(to, from, n); - else - memset(to, 0, n); - return n; + return __xtensa_copy_user((__force void *)to, from, n); } - -#define copy_to_user(to, from, n) __generic_copy_to_user((to), (from), (n)) -#define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n)) -#define __copy_to_user(to, from, n) \ - __generic_copy_to_user_nocheck((to), (from), (n)) -#define __copy_from_user(to, from, n) \ - __generic_copy_from_user_nocheck((to), (from), (n)) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * We need to return the number of bytes not cleared. Our memset() @@ -348,10 +305,4 @@ static inline long strnlen_user(const char *str, long len) return __strnlen_user(str, len); } - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - #endif /* _XTENSA_UACCESS_H */ diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index 9fdbe1fe0473..1eb6d2fe70d3 100644 --- a/arch/xtensa/include/uapi/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h @@ -103,4 +103,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _XTENSA_SOCKET_H */ diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index cd400af4a6b2..6be7eb27fd29 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -774,7 +774,10 @@ __SYSCALL(349, sys_pkey_alloc, 2) #define __NR_pkey_free 350 __SYSCALL(350, sys_pkey_free, 1) -#define __NR_syscall_count 351 +#define __NR_statx 351 +__SYSCALL(351, sys_statx, 5) + +#define __NR_syscall_count 352 /* * sysxtensa syscall handler diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index c82c43bff296..bae697a06a98 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -483,10 +483,8 @@ void show_regs(struct pt_regs * regs) static int show_trace_cb(struct stackframe *frame, void *data) { - if (kernel_text_address(frame->pc)) { - pr_cont(" [<%08lx>]", frame->pc); - print_symbol(" %s\n", frame->pc); - } + if (kernel_text_address(frame->pc)) + pr_cont(" [<%08lx>] %pB\n", frame->pc, (void *)frame->pc); return 0; } diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S index 7ea4dd68893e..d9cd766bde3e 100644 --- a/arch/xtensa/lib/usercopy.S +++ b/arch/xtensa/lib/usercopy.S @@ -102,9 +102,9 @@ __xtensa_copy_user: bltui a4, 7, .Lbytecopy # do short copies byte by byte # copy 1 byte - EX(l8ui, a6, a3, 0, l_fixup) + EX(l8ui, a6, a3, 0, fixup) addi a3, a3, 1 - EX(s8i, a6, a5, 0, s_fixup) + EX(s8i, a6, a5, 0, fixup) addi a5, a5, 1 addi a4, a4, -1 bbci.l a5, 1, .Ldstaligned # if dst is now aligned, then @@ -112,11 +112,11 @@ __xtensa_copy_user: .Ldst2mod4: # dst 16-bit aligned # copy 2 bytes bltui a4, 6, .Lbytecopy # do short copies byte by byte - EX(l8ui, a6, a3, 0, l_fixup) - EX(l8ui, a7, a3, 1, l_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(l8ui, a7, a3, 1, fixup) addi a3, a3, 2 - EX(s8i, a6, a5, 0, s_fixup) - EX(s8i, a7, a5, 1, s_fixup) + EX(s8i, a6, a5, 0, fixup) + EX(s8i, a7, a5, 1, fixup) addi a5, a5, 2 addi a4, a4, -2 j .Ldstaligned # dst is now aligned, return to main algorithm @@ -135,9 +135,9 @@ __xtensa_copy_user: add a7, a3, a4 # a7 = end address for source #endif /* !XCHAL_HAVE_LOOPS */ .Lnextbyte: - EX(l8ui, a6, a3, 0, l_fixup) + EX(l8ui, a6, a3, 0, fixup) addi a3, a3, 1 - EX(s8i, a6, a5, 0, s_fixup) + EX(s8i, a6, a5, 0, fixup) addi a5, a5, 1 #if !XCHAL_HAVE_LOOPS blt a3, a7, .Lnextbyte @@ -161,15 +161,15 @@ __xtensa_copy_user: add a8, a8, a3 # a8 = end of last 16B source chunk #endif /* !XCHAL_HAVE_LOOPS */ .Loop1: - EX(l32i, a6, a3, 0, l_fixup) - EX(l32i, a7, a3, 4, l_fixup) - EX(s32i, a6, a5, 0, s_fixup) - EX(l32i, a6, a3, 8, l_fixup) - EX(s32i, a7, a5, 4, s_fixup) - EX(l32i, a7, a3, 12, l_fixup) - EX(s32i, a6, a5, 8, s_fixup) + EX(l32i, a6, a3, 0, fixup) + EX(l32i, a7, a3, 4, fixup) + EX(s32i, a6, a5, 0, fixup) + EX(l32i, a6, a3, 8, fixup) + EX(s32i, a7, a5, 4, fixup) + EX(l32i, a7, a3, 12, fixup) + EX(s32i, a6, a5, 8, fixup) addi a3, a3, 16 - EX(s32i, a7, a5, 12, s_fixup) + EX(s32i, a7, a5, 12, fixup) addi a5, a5, 16 #if !XCHAL_HAVE_LOOPS blt a3, a8, .Loop1 @@ -177,31 +177,31 @@ __xtensa_copy_user: .Loop1done: bbci.l a4, 3, .L2 # copy 8 bytes - EX(l32i, a6, a3, 0, l_fixup) - EX(l32i, a7, a3, 4, l_fixup) + EX(l32i, a6, a3, 0, fixup) + EX(l32i, a7, a3, 4, fixup) addi a3, a3, 8 - EX(s32i, a6, a5, 0, s_fixup) - EX(s32i, a7, a5, 4, s_fixup) + EX(s32i, a6, a5, 0, fixup) + EX(s32i, a7, a5, 4, fixup) addi a5, a5, 8 .L2: bbci.l a4, 2, .L3 # copy 4 bytes - EX(l32i, a6, a3, 0, l_fixup) + EX(l32i, a6, a3, 0, fixup) addi a3, a3, 4 - EX(s32i, a6, a5, 0, s_fixup) + EX(s32i, a6, a5, 0, fixup) addi a5, a5, 4 .L3: bbci.l a4, 1, .L4 # copy 2 bytes - EX(l16ui, a6, a3, 0, l_fixup) + EX(l16ui, a6, a3, 0, fixup) addi a3, a3, 2 - EX(s16i, a6, a5, 0, s_fixup) + EX(s16i, a6, a5, 0, fixup) addi a5, a5, 2 .L4: bbci.l a4, 0, .L5 # copy 1 byte - EX(l8ui, a6, a3, 0, l_fixup) - EX(s8i, a6, a5, 0, s_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(s8i, a6, a5, 0, fixup) .L5: movi a2, 0 # return success for len bytes copied retw @@ -217,7 +217,7 @@ __xtensa_copy_user: # copy 16 bytes per iteration for word-aligned dst and unaligned src and a10, a3, a8 # save unalignment offset for below sub a3, a3, a10 # align a3 (to avoid sim warnings only; not needed for hardware) - EX(l32i, a6, a3, 0, l_fixup) # load first word + EX(l32i, a6, a3, 0, fixup) # load first word #if XCHAL_HAVE_LOOPS loopnez a7, .Loop2done #else /* !XCHAL_HAVE_LOOPS */ @@ -226,19 +226,19 @@ __xtensa_copy_user: add a12, a12, a3 # a12 = end of last 16B source chunk #endif /* !XCHAL_HAVE_LOOPS */ .Loop2: - EX(l32i, a7, a3, 4, l_fixup) - EX(l32i, a8, a3, 8, l_fixup) + EX(l32i, a7, a3, 4, fixup) + EX(l32i, a8, a3, 8, fixup) ALIGN( a6, a6, a7) - EX(s32i, a6, a5, 0, s_fixup) - EX(l32i, a9, a3, 12, l_fixup) + EX(s32i, a6, a5, 0, fixup) + EX(l32i, a9, a3, 12, fixup) ALIGN( a7, a7, a8) - EX(s32i, a7, a5, 4, s_fixup) - EX(l32i, a6, a3, 16, l_fixup) + EX(s32i, a7, a5, 4, fixup) + EX(l32i, a6, a3, 16, fixup) ALIGN( a8, a8, a9) - EX(s32i, a8, a5, 8, s_fixup) + EX(s32i, a8, a5, 8, fixup) addi a3, a3, 16 ALIGN( a9, a9, a6) - EX(s32i, a9, a5, 12, s_fixup) + EX(s32i, a9, a5, 12, fixup) addi a5, a5, 16 #if !XCHAL_HAVE_LOOPS blt a3, a12, .Loop2 @@ -246,39 +246,39 @@ __xtensa_copy_user: .Loop2done: bbci.l a4, 3, .L12 # copy 8 bytes - EX(l32i, a7, a3, 4, l_fixup) - EX(l32i, a8, a3, 8, l_fixup) + EX(l32i, a7, a3, 4, fixup) + EX(l32i, a8, a3, 8, fixup) ALIGN( a6, a6, a7) - EX(s32i, a6, a5, 0, s_fixup) + EX(s32i, a6, a5, 0, fixup) addi a3, a3, 8 ALIGN( a7, a7, a8) - EX(s32i, a7, a5, 4, s_fixup) + EX(s32i, a7, a5, 4, fixup) addi a5, a5, 8 mov a6, a8 .L12: bbci.l a4, 2, .L13 # copy 4 bytes - EX(l32i, a7, a3, 4, l_fixup) + EX(l32i, a7, a3, 4, fixup) addi a3, a3, 4 ALIGN( a6, a6, a7) - EX(s32i, a6, a5, 0, s_fixup) + EX(s32i, a6, a5, 0, fixup) addi a5, a5, 4 mov a6, a7 .L13: add a3, a3, a10 # readjust a3 with correct misalignment bbci.l a4, 1, .L14 # copy 2 bytes - EX(l8ui, a6, a3, 0, l_fixup) - EX(l8ui, a7, a3, 1, l_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(l8ui, a7, a3, 1, fixup) addi a3, a3, 2 - EX(s8i, a6, a5, 0, s_fixup) - EX(s8i, a7, a5, 1, s_fixup) + EX(s8i, a6, a5, 0, fixup) + EX(s8i, a7, a5, 1, fixup) addi a5, a5, 2 .L14: bbci.l a4, 0, .L15 # copy 1 byte - EX(l8ui, a6, a3, 0, l_fixup) - EX(s8i, a6, a5, 0, s_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(s8i, a6, a5, 0, fixup) .L15: movi a2, 0 # return success for len bytes copied retw @@ -291,30 +291,10 @@ __xtensa_copy_user: * bytes_copied = a5 - a2 * retval = bytes_not_copied = original len - bytes_copied * retval = a11 - (a5 - a2) - * - * Clearing the remaining pieces of kernel memory plugs security - * holes. This functionality is the equivalent of the *_zeroing - * functions that some architectures provide. */ -.Lmemset: - .word memset -s_fixup: +fixup: sub a2, a5, a2 /* a2 <-- bytes copied */ sub a2, a11, a2 /* a2 <-- bytes not copied */ retw - -l_fixup: - sub a2, a5, a2 /* a2 <-- bytes copied */ - sub a2, a11, a2 /* a2 <-- bytes not copied == return value */ - - /* void *memset(void *s, int c, size_t n); */ - mov a6, a5 /* s */ - movi a7, 0 /* c */ - mov a8, a2 /* n */ - l32r a4, .Lmemset - callx4 a4 - /* Ignore memset return value in a6. */ - /* a2 still contains bytes not copied. */ - retw |