aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/include
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-06-25 17:04:17 -0400
committerChris Metcalf <cmetcalf@tilera.com>2010-07-06 13:41:51 -0400
commit0707ad30d10110aebc01a5a64fb63f4b32d20b73 (patch)
tree64d8ba73e605ac26e56808d1d77701b3f83cf8b2 /arch/tile/include
parentc78095bd8c77fca2619769ff8efb639fd100e373 (diff)
arch/tile: Miscellaneous cleanup changes.
This commit is primarily changes caused by reviewing "sparse" and "checkpatch" output on our sources, so is somewhat noisy, since things like "printk() -> pr_err()" (or whatever) throughout the codebase tend to get tedious to read. Rather than trying to tease apart precisely which things changed due to which type of code review, this commit includes various cleanups in the code: - sparse: Add declarations in headers for globals. - sparse: Fix __user annotations. - sparse: Using gfp_t consistently instead of int. - sparse: removing functions not actually used. - checkpatch: Clean up printk() warnings by using pr_info(), etc.; also avoid partial-line printks except in bootup code. - checkpatch: Use exposed structs rather than typedefs. - checkpatch: Change some C99 comments to C89 comments. In addition, a couple of minor other changes are rolled in to this commit: - Add support for a "raise" instruction to cause SIGFPE, etc., to be raised. - Remove some compat code that is unnecessary when we fully eliminate some of the deprecated syscalls from the generic syscall ABI. - Update the tile_defconfig to reflect current config contents. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/tile/include')
-rw-r--r--arch/tile/include/arch/abi.h69
-rw-r--r--arch/tile/include/arch/interrupts_32.h2
-rw-r--r--arch/tile/include/asm/atomic_32.h17
-rw-r--r--arch/tile/include/asm/compat.h55
-rw-r--r--arch/tile/include/asm/elf.h6
-rw-r--r--arch/tile/include/asm/futex.h17
-rw-r--r--arch/tile/include/asm/page.h9
-rw-r--r--arch/tile/include/asm/pgtable.h9
-rw-r--r--arch/tile/include/asm/pgtable_32.h12
-rw-r--r--arch/tile/include/asm/ptrace.h5
-rw-r--r--arch/tile/include/asm/sections.h9
-rw-r--r--arch/tile/include/asm/signal.h1
-rw-r--r--arch/tile/include/asm/spinlock_32.h3
-rw-r--r--arch/tile/include/asm/stack.h6
-rw-r--r--arch/tile/include/asm/syscalls.h72
-rw-r--r--arch/tile/include/asm/system.h30
-rw-r--r--arch/tile/include/asm/thread_info.h8
-rw-r--r--arch/tile/include/asm/traps.h26
-rw-r--r--arch/tile/include/asm/uaccess.h22
-rw-r--r--arch/tile/include/asm/unistd.h9
20 files changed, 265 insertions, 122 deletions
diff --git a/arch/tile/include/arch/abi.h b/arch/tile/include/arch/abi.h
index 7cdc47b3e02a..da8df5b9d914 100644
--- a/arch/tile/include/arch/abi.h
+++ b/arch/tile/include/arch/abi.h
@@ -1,26 +1,29 @@
1// Copyright 2010 Tilera Corporation. All Rights Reserved. 1/*
2// 2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3// This program is free software; you can redistribute it and/or 3 *
4// modify it under the terms of the GNU General Public License 4 * This program is free software; you can redistribute it and/or
5// as published by the Free Software Foundation, version 2. 5 * modify it under the terms of the GNU General Public License
6// 6 * as published by the Free Software Foundation, version 2.
7// This program is distributed in the hope that it will be useful, but 7 *
8// WITHOUT ANY WARRANTY; without even the implied warranty of 8 * This program is distributed in the hope that it will be useful, but
9// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10// NON INFRINGEMENT. See the GNU General Public License for 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11// more details. 11 * NON INFRINGEMENT. See the GNU General Public License for
12 12 * more details.
13//! @file 13 */
14//! 14
15//! ABI-related register definitions helpful when writing assembly code. 15/**
16//! 16 * @file
17 *
18 * ABI-related register definitions helpful when writing assembly code.
19 */
17 20
18#ifndef __ARCH_ABI_H__ 21#ifndef __ARCH_ABI_H__
19#define __ARCH_ABI_H__ 22#define __ARCH_ABI_H__
20 23
21#include <arch/chip.h> 24#include <arch/chip.h>
22 25
23// Registers 0 - 55 are "normal", but some perform special roles. 26/* Registers 0 - 55 are "normal", but some perform special roles. */
24 27
25#define TREG_FP 52 /**< Frame pointer. */ 28#define TREG_FP 52 /**< Frame pointer. */
26#define TREG_TP 53 /**< Thread pointer. */ 29#define TREG_TP 53 /**< Thread pointer. */
@@ -30,7 +33,7 @@
30/** Index of last normal general-purpose register. */ 33/** Index of last normal general-purpose register. */
31#define TREG_LAST_GPR 55 34#define TREG_LAST_GPR 55
32 35
33// Registers 56 - 62 are "special" network registers. 36/* Registers 56 - 62 are "special" network registers. */
34 37
35#define TREG_SN 56 /**< Static network access. */ 38#define TREG_SN 56 /**< Static network access. */
36#define TREG_IDN0 57 /**< IDN demux 0 access. */ 39#define TREG_IDN0 57 /**< IDN demux 0 access. */
@@ -40,7 +43,7 @@
40#define TREG_UDN2 61 /**< UDN demux 2 access. */ 43#define TREG_UDN2 61 /**< UDN demux 2 access. */
41#define TREG_UDN3 62 /**< UDN demux 3 access. */ 44#define TREG_UDN3 62 /**< UDN demux 3 access. */
42 45
43// Register 63 is the "special" zero register. 46/* Register 63 is the "special" zero register. */
44 47
45#define TREG_ZERO 63 /**< "Zero" register; always reads as "0". */ 48#define TREG_ZERO 63 /**< "Zero" register; always reads as "0". */
46 49
@@ -52,42 +55,44 @@
52#define TREG_SYSCALL_NR_NAME r10 55#define TREG_SYSCALL_NR_NAME r10
53 56
54 57
55//! The ABI requires callers to allocate a caller state save area of 58/**
56//! this many bytes at the bottom of each stack frame. 59 * The ABI requires callers to allocate a caller state save area of
57//! 60 * this many bytes at the bottom of each stack frame.
61 */
58#ifdef __tile__ 62#ifdef __tile__
59#define C_ABI_SAVE_AREA_SIZE (2 * __SIZEOF_POINTER__) 63#define C_ABI_SAVE_AREA_SIZE (2 * __SIZEOF_POINTER__)
60#endif 64#endif
61 65
62//! The operand to an 'info' opcode directing the backtracer to not 66/**
63//! try to find the calling frame. 67 * The operand to an 'info' opcode directing the backtracer to not
64//! 68 * try to find the calling frame.
69 */
65#define INFO_OP_CANNOT_BACKTRACE 2 70#define INFO_OP_CANNOT_BACKTRACE 2
66 71
67#ifndef __ASSEMBLER__ 72#ifndef __ASSEMBLER__
68#if CHIP_WORD_SIZE() > 32 73#if CHIP_WORD_SIZE() > 32
69 74
70//! Unsigned type that can hold a register. 75/** Unsigned type that can hold a register. */
71typedef unsigned long long uint_reg_t; 76typedef unsigned long long uint_reg_t;
72 77
73//! Signed type that can hold a register. 78/** Signed type that can hold a register. */
74typedef long long int_reg_t; 79typedef long long int_reg_t;
75 80
76//! String prefix to use for printf(). 81/** String prefix to use for printf(). */
77#define INT_REG_FMT "ll" 82#define INT_REG_FMT "ll"
78 83
79#elif !defined(__LP64__) /* avoid confusion with LP64 cross-build tools */ 84#elif !defined(__LP64__) /* avoid confusion with LP64 cross-build tools */
80 85
81//! Unsigned type that can hold a register. 86/** Unsigned type that can hold a register. */
82typedef unsigned long uint_reg_t; 87typedef unsigned long uint_reg_t;
83 88
84//! Signed type that can hold a register. 89/** Signed type that can hold a register. */
85typedef long int_reg_t; 90typedef long int_reg_t;
86 91
87//! String prefix to use for printf(). 92/** String prefix to use for printf(). */
88#define INT_REG_FMT "l" 93#define INT_REG_FMT "l"
89 94
90#endif 95#endif
91#endif /* __ASSEMBLER__ */ 96#endif /* __ASSEMBLER__ */
92 97
93#endif // !__ARCH_ABI_H__ 98#endif /* !__ARCH_ABI_H__ */
diff --git a/arch/tile/include/arch/interrupts_32.h b/arch/tile/include/arch/interrupts_32.h
index feffada705f0..9d0bfa7e59be 100644
--- a/arch/tile/include/arch/interrupts_32.h
+++ b/arch/tile/include/arch/interrupts_32.h
@@ -301,4 +301,4 @@
301 INT_MASK(INT_DOUBLE_FAULT) | \ 301 INT_MASK(INT_DOUBLE_FAULT) | \
302 INT_MASK(INT_AUX_PERF_COUNT) | \ 302 INT_MASK(INT_AUX_PERF_COUNT) | \
303 0) 303 0)
304#endif // !__ARCH_INTERRUPTS_H__ 304#endif /* !__ARCH_INTERRUPTS_H__ */
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index e4f8b4f04895..40a5a3a876d9 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -348,6 +348,23 @@ void __init_atomic_per_cpu(void);
348/* Support releasing the atomic lock in do_page_fault_ics(). */ 348/* Support releasing the atomic lock in do_page_fault_ics(). */
349void __atomic_fault_unlock(int *lock_ptr); 349void __atomic_fault_unlock(int *lock_ptr);
350#endif 350#endif
351
352/* Private helper routines in lib/atomic_asm_32.S */
353extern struct __get_user __atomic_cmpxchg(volatile int *p,
354 int *lock, int o, int n);
355extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n);
356extern struct __get_user __atomic_xchg_add(volatile int *p, int *lock, int n);
357extern struct __get_user __atomic_xchg_add_unless(volatile int *p,
358 int *lock, int o, int n);
359extern struct __get_user __atomic_or(volatile int *p, int *lock, int n);
360extern struct __get_user __atomic_andn(volatile int *p, int *lock, int n);
361extern struct __get_user __atomic_xor(volatile int *p, int *lock, int n);
362extern u64 __atomic64_cmpxchg(volatile u64 *p, int *lock, u64 o, u64 n);
363extern u64 __atomic64_xchg(volatile u64 *p, int *lock, u64 n);
364extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n);
365extern u64 __atomic64_xchg_add_unless(volatile u64 *p,
366 int *lock, u64 o, u64 n);
367
351#endif /* !__ASSEMBLY__ */ 368#endif /* !__ASSEMBLY__ */
352 369
353#endif /* _ASM_TILE_ATOMIC_32_H */ 370#endif /* _ASM_TILE_ATOMIC_32_H */
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index b09292bcc19f..5a34da6cdd79 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -70,48 +70,7 @@ struct compat_timeval {
70 s32 tv_usec; 70 s32 tv_usec;
71}; 71};
72 72
73struct compat_stat { 73#define compat_stat stat
74 unsigned int st_dev;
75 unsigned int st_ino;
76 unsigned int st_mode;
77 unsigned int st_nlink;
78 unsigned int st_uid;
79 unsigned int st_gid;
80 unsigned int st_rdev;
81 unsigned int __pad1;
82 int st_size;
83 int st_blksize;
84 int __pad2;
85 int st_blocks;
86 int st_atime;
87 unsigned int st_atime_nsec;
88 int st_mtime;
89 unsigned int st_mtime_nsec;
90 int st_ctime;
91 unsigned int st_ctime_nsec;
92 unsigned int __unused[2];
93};
94
95struct compat_stat64 {
96 unsigned long st_dev;
97 unsigned long st_ino;
98 unsigned int st_mode;
99 unsigned int st_nlink;
100 unsigned int st_uid;
101 unsigned int st_gid;
102 unsigned long st_rdev;
103 long st_size;
104 unsigned int st_blksize;
105 unsigned long st_blocks __attribute__((packed));
106 unsigned int st_atime;
107 unsigned int st_atime_nsec;
108 unsigned int st_mtime;
109 unsigned int st_mtime_nsec;
110 unsigned int st_ctime;
111 unsigned int st_ctime_nsec;
112 unsigned int __unused8;
113};
114
115#define compat_statfs statfs 74#define compat_statfs statfs
116 75
117struct compat_sysctl { 76struct compat_sysctl {
@@ -233,7 +192,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
233/* Sign-extend when storing a kernel pointer to a user's ptregs. */ 192/* Sign-extend when storing a kernel pointer to a user's ptregs. */
234static inline unsigned long ptr_to_compat_reg(void __user *uptr) 193static inline unsigned long ptr_to_compat_reg(void __user *uptr)
235{ 194{
236 return (long)(int)(long)uptr; 195 return (long)(int)(long __force)uptr;
237} 196}
238 197
239static inline void __user *compat_alloc_user_space(long len) 198static inline void __user *compat_alloc_user_space(long len)
@@ -278,17 +237,8 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags,
278long compat_sys_fallocate(int fd, int mode, 237long compat_sys_fallocate(int fd, int mode,
279 u32 offset_lo, u32 offset_hi, 238 u32 offset_lo, u32 offset_hi,
280 u32 len_lo, u32 len_hi); 239 u32 len_lo, u32 len_hi);
281long compat_sys_stat64(char __user *filename,
282 struct compat_stat64 __user *statbuf);
283long compat_sys_lstat64(char __user *filename,
284 struct compat_stat64 __user *statbuf);
285long compat_sys_fstat64(unsigned int fd, struct compat_stat64 __user *statbuf);
286long compat_sys_fstatat64(int dfd, char __user *filename,
287 struct compat_stat64 __user *statbuf, int flag);
288long compat_sys_sched_rr_get_interval(compat_pid_t pid, 240long compat_sys_sched_rr_get_interval(compat_pid_t pid,
289 struct compat_timespec __user *interval); 241 struct compat_timespec __user *interval);
290ssize_t compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
291 size_t count);
292 242
293/* Versions of compat functions that differ from generic Linux. */ 243/* Versions of compat functions that differ from generic Linux. */
294struct compat_msgbuf; 244struct compat_msgbuf;
@@ -302,7 +252,6 @@ long tile_compat_sys_ptrace(compat_long_t request, compat_long_t pid,
302 compat_long_t addr, compat_long_t data); 252 compat_long_t addr, compat_long_t data);
303 253
304/* Tilera Linux syscalls that don't have "compat" versions. */ 254/* Tilera Linux syscalls that don't have "compat" versions. */
305#define compat_sys_raise_fpe sys_raise_fpe
306#define compat_sys_flush_cache sys_flush_cache 255#define compat_sys_flush_cache sys_flush_cache
307 256
308#endif /* _ASM_TILE_COMPAT_H */ 257#endif /* _ASM_TILE_COMPAT_H */
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index 1bca0debdb0f..623a6bb741c1 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -59,8 +59,7 @@ enum { ELF_ARCH = CHIP_ELF_TYPE() };
59 */ 59 */
60#define elf_check_arch(x) \ 60#define elf_check_arch(x) \
61 ((x)->e_ident[EI_CLASS] == ELF_CLASS && \ 61 ((x)->e_ident[EI_CLASS] == ELF_CLASS && \
62 ((x)->e_machine == CHIP_ELF_TYPE() || \ 62 (x)->e_machine == CHIP_ELF_TYPE())
63 (x)->e_machine == CHIP_COMPAT_ELF_TYPE()))
64 63
65/* The module loader only handles a few relocation types. */ 64/* The module loader only handles a few relocation types. */
66#ifndef __tilegx__ 65#ifndef __tilegx__
@@ -139,8 +138,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
139 */ 138 */
140#define compat_elf_check_arch(x) \ 139#define compat_elf_check_arch(x) \
141 ((x)->e_ident[EI_CLASS] == ELFCLASS32 && \ 140 ((x)->e_ident[EI_CLASS] == ELFCLASS32 && \
142 ((x)->e_machine == CHIP_ELF_TYPE() || \ 141 (x)->e_machine == CHIP_ELF_TYPE())
143 (x)->e_machine == CHIP_COMPAT_ELF_TYPE()))
144 142
145#define compat_start_thread(regs, ip, usp) do { \ 143#define compat_start_thread(regs, ip, usp) do { \
146 regs->pc = ptr_to_compat_reg((void *)(ip)); \ 144 regs->pc = ptr_to_compat_reg((void *)(ip)); \
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index 9eaeb3c08786..fe0d10dcae57 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -29,14 +29,14 @@
29#include <linux/uaccess.h> 29#include <linux/uaccess.h>
30#include <linux/errno.h> 30#include <linux/errno.h>
31 31
32extern struct __get_user futex_set(int *v, int i); 32extern struct __get_user futex_set(int __user *v, int i);
33extern struct __get_user futex_add(int *v, int n); 33extern struct __get_user futex_add(int __user *v, int n);
34extern struct __get_user futex_or(int *v, int n); 34extern struct __get_user futex_or(int __user *v, int n);
35extern struct __get_user futex_andn(int *v, int n); 35extern struct __get_user futex_andn(int __user *v, int n);
36extern struct __get_user futex_cmpxchg(int *v, int o, int n); 36extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
37 37
38#ifndef __tilegx__ 38#ifndef __tilegx__
39extern struct __get_user futex_xor(int *v, int n); 39extern struct __get_user futex_xor(int __user *v, int n);
40#else 40#else
41static inline struct __get_user futex_xor(int __user *uaddr, int n) 41static inline struct __get_user futex_xor(int __user *uaddr, int n)
42{ 42{
@@ -131,6 +131,11 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
131 return asm_ret.err ? asm_ret.err : asm_ret.val; 131 return asm_ret.err ? asm_ret.err : asm_ret.val;
132} 132}
133 133
134#ifndef __tilegx__
135/* Return failure from the atomic wrappers. */
136struct __get_user __atomic_bad_address(int __user *addr);
137#endif
138
134#endif /* !__ASSEMBLY__ */ 139#endif /* !__ASSEMBLY__ */
135 140
136#endif /* _ASM_TILE_FUTEX_H */ 141#endif /* _ASM_TILE_FUTEX_H */
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index c8301c43d6d9..f894a9016da6 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -16,8 +16,6 @@
16#define _ASM_TILE_PAGE_H 16#define _ASM_TILE_PAGE_H
17 17
18#include <linux/const.h> 18#include <linux/const.h>
19#include <hv/hypervisor.h>
20#include <arch/chip.h>
21 19
22/* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */ 20/* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */
23#define PAGE_SHIFT 16 21#define PAGE_SHIFT 16
@@ -29,6 +27,11 @@
29#define PAGE_MASK (~(PAGE_SIZE - 1)) 27#define PAGE_MASK (~(PAGE_SIZE - 1))
30#define HPAGE_MASK (~(HPAGE_SIZE - 1)) 28#define HPAGE_MASK (~(HPAGE_SIZE - 1))
31 29
30#ifdef __KERNEL__
31
32#include <hv/hypervisor.h>
33#include <arch/chip.h>
34
32/* 35/*
33 * The {,H}PAGE_SHIFT values must match the HV_LOG2_PAGE_SIZE_xxx 36 * The {,H}PAGE_SHIFT values must match the HV_LOG2_PAGE_SIZE_xxx
34 * definitions in <hv/hypervisor.h>. We validate this at build time 37 * definitions in <hv/hypervisor.h>. We validate this at build time
@@ -331,4 +334,6 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
331#include <asm-generic/memory_model.h> 334#include <asm-generic/memory_model.h>
332#include <asm-generic/getorder.h> 335#include <asm-generic/getorder.h>
333 336
337#endif /* __KERNEL__ */
338
334#endif /* _ASM_TILE_PAGE_H */ 339#endif /* _ASM_TILE_PAGE_H */
diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h
index beb1504e9c10..b3367379d537 100644
--- a/arch/tile/include/asm/pgtable.h
+++ b/arch/tile/include/asm/pgtable.h
@@ -229,9 +229,9 @@ static inline void __pte_clear(pte_t *ptep)
229#define pte_donemigrate(x) hv_pte_set_present(hv_pte_clear_migrating(x)) 229#define pte_donemigrate(x) hv_pte_set_present(hv_pte_clear_migrating(x))
230 230
231#define pte_ERROR(e) \ 231#define pte_ERROR(e) \
232 printk("%s:%d: bad pte 0x%016llx.\n", __FILE__, __LINE__, pte_val(e)) 232 pr_err("%s:%d: bad pte 0x%016llx.\n", __FILE__, __LINE__, pte_val(e))
233#define pgd_ERROR(e) \ 233#define pgd_ERROR(e) \
234 printk("%s:%d: bad pgd 0x%016llx.\n", __FILE__, __LINE__, pgd_val(e)) 234 pr_err("%s:%d: bad pgd 0x%016llx.\n", __FILE__, __LINE__, pgd_val(e))
235 235
236/* 236/*
237 * set_pte_order() sets the given PTE and also sanity-checks the 237 * set_pte_order() sets the given PTE and also sanity-checks the
@@ -470,6 +470,11 @@ static inline int pmd_huge_page(pmd_t pmd)
470 470
471#include <asm-generic/pgtable.h> 471#include <asm-generic/pgtable.h>
472 472
473/* Support /proc/NN/pgtable API. */
474struct seq_file;
475int arch_proc_pgtable_show(struct seq_file *m, struct mm_struct *mm,
476 unsigned long vaddr, pte_t *ptep, void **datap);
477
473#endif /* !__ASSEMBLY__ */ 478#endif /* !__ASSEMBLY__ */
474 479
475#endif /* _ASM_TILE_PGTABLE_H */ 480#endif /* _ASM_TILE_PGTABLE_H */
diff --git a/arch/tile/include/asm/pgtable_32.h b/arch/tile/include/asm/pgtable_32.h
index b935fb2ad4f3..53ec34884744 100644
--- a/arch/tile/include/asm/pgtable_32.h
+++ b/arch/tile/include/asm/pgtable_32.h
@@ -89,15 +89,27 @@ static inline int pgd_addr_invalid(unsigned long addr)
89/* 89/*
90 * Provide versions of these routines that can be used safely when 90 * Provide versions of these routines that can be used safely when
91 * the hypervisor may be asynchronously modifying dirty/accessed bits. 91 * the hypervisor may be asynchronously modifying dirty/accessed bits.
92 * ptep_get_and_clear() matches the generic one but we provide it to
93 * be parallel with the 64-bit code.
92 */ 94 */
93#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 95#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
94#define __HAVE_ARCH_PTEP_SET_WRPROTECT 96#define __HAVE_ARCH_PTEP_SET_WRPROTECT
97#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
95 98
96extern int ptep_test_and_clear_young(struct vm_area_struct *, 99extern int ptep_test_and_clear_young(struct vm_area_struct *,
97 unsigned long addr, pte_t *); 100 unsigned long addr, pte_t *);
98extern void ptep_set_wrprotect(struct mm_struct *, 101extern void ptep_set_wrprotect(struct mm_struct *,
99 unsigned long addr, pte_t *); 102 unsigned long addr, pte_t *);
100 103
104#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
105static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
106 unsigned long addr, pte_t *ptep)
107{
108 pte_t pte = *ptep;
109 pte_clear(_mm, addr, ptep);
110 return pte;
111}
112
101/* Create a pmd from a PTFN. */ 113/* Create a pmd from a PTFN. */
102static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot) 114static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot)
103{ 115{
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index 4d1d9953016a..acdae814e016 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -112,6 +112,9 @@ struct pt_regs {
112/* Fill in a struct pt_regs with the current kernel registers. */ 112/* Fill in a struct pt_regs with the current kernel registers. */
113struct pt_regs *get_pt_regs(struct pt_regs *); 113struct pt_regs *get_pt_regs(struct pt_regs *);
114 114
115/* Trace the current syscall. */
116extern void do_syscall_trace(void);
117
115extern void show_regs(struct pt_regs *); 118extern void show_regs(struct pt_regs *);
116 119
117#define arch_has_single_step() (1) 120#define arch_has_single_step() (1)
@@ -123,7 +126,7 @@ extern void show_regs(struct pt_regs *);
123 */ 126 */
124struct single_step_state { 127struct single_step_state {
125 /* the page to which we will write hacked-up bundles */ 128 /* the page to which we will write hacked-up bundles */
126 void *buffer; 129 void __user *buffer;
127 130
128 union { 131 union {
129 int flags; 132 int flags;
diff --git a/arch/tile/include/asm/sections.h b/arch/tile/include/asm/sections.h
index 6c111491f0ed..d062d463fca9 100644
--- a/arch/tile/include/asm/sections.h
+++ b/arch/tile/include/asm/sections.h
@@ -25,7 +25,14 @@ extern char _sinitdata[], _einitdata[];
25/* Write-once data is writable only till the end of initialization. */ 25/* Write-once data is writable only till the end of initialization. */
26extern char __w1data_begin[], __w1data_end[]; 26extern char __w1data_begin[], __w1data_end[];
27 27
28extern char __feedback_section_start[], __feedback_section_end[]; 28
29/* Not exactly sections, but PC comparison points in the code. */
30extern char __rt_sigreturn[], __rt_sigreturn_end[];
31#ifndef __tilegx__
32extern char sys_cmpxchg[], __sys_cmpxchg_end[];
33extern char __sys_cmpxchg_grab_lock[];
34extern char __start_atomic_asm_code[], __end_atomic_asm_code[];
35#endif
29 36
30/* Handle the discontiguity between _sdata and _stext. */ 37/* Handle the discontiguity between _sdata and _stext. */
31static inline int arch_is_kernel_data(unsigned long addr) 38static inline int arch_is_kernel_data(unsigned long addr)
diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h
index d20d326d201b..eb0253f32202 100644
--- a/arch/tile/include/asm/signal.h
+++ b/arch/tile/include/asm/signal.h
@@ -26,6 +26,7 @@
26#if defined(__KERNEL__) && !defined(__ASSEMBLY__) 26#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
27int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); 27int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
28int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); 28int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
29void do_signal(struct pt_regs *regs);
29#endif 30#endif
30 31
31#endif /* _ASM_TILE_SIGNAL_H */ 32#endif /* _ASM_TILE_SIGNAL_H */
diff --git a/arch/tile/include/asm/spinlock_32.h b/arch/tile/include/asm/spinlock_32.h
index f3a8473c68da..88efdde8dd2b 100644
--- a/arch/tile/include/asm/spinlock_32.h
+++ b/arch/tile/include/asm/spinlock_32.h
@@ -134,9 +134,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rwlock)
134{ 134{
135 int locked; 135 int locked;
136 u32 val = __insn_tns((int *)&rwlock->lock); 136 u32 val = __insn_tns((int *)&rwlock->lock);
137 if (unlikely(val & 1)) { 137 if (unlikely(val & 1))
138 return arch_read_trylock_slow(rwlock); 138 return arch_read_trylock_slow(rwlock);
139 }
140 locked = (val << _RD_COUNT_WIDTH) == 0; 139 locked = (val << _RD_COUNT_WIDTH) == 0;
141 rwlock->lock = val + (locked << _RD_COUNT_SHIFT); 140 rwlock->lock = val + (locked << _RD_COUNT_SHIFT);
142 return locked; 141 return locked;
diff --git a/arch/tile/include/asm/stack.h b/arch/tile/include/asm/stack.h
index 864913bcfbc9..f908473c322d 100644
--- a/arch/tile/include/asm/stack.h
+++ b/arch/tile/include/asm/stack.h
@@ -48,6 +48,10 @@ extern void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
48/* Initialize iterator based on current stack. */ 48/* Initialize iterator based on current stack. */
49extern void KBacktraceIterator_init_current(struct KBacktraceIterator *kbt); 49extern void KBacktraceIterator_init_current(struct KBacktraceIterator *kbt);
50 50
51/* Helper method for above. */
52extern void _KBacktraceIterator_init_current(struct KBacktraceIterator *kbt,
53 ulong pc, ulong lr, ulong sp, ulong r52);
54
51/* No more frames? */ 55/* No more frames? */
52extern int KBacktraceIterator_end(struct KBacktraceIterator *kbt); 56extern int KBacktraceIterator_end(struct KBacktraceIterator *kbt);
53 57
@@ -64,5 +68,7 @@ extern void tile_show_stack(struct KBacktraceIterator *, int headers);
64/* Dump stack of current process, with registers to seed the backtrace. */ 68/* Dump stack of current process, with registers to seed the backtrace. */
65extern void dump_stack_regs(struct pt_regs *); 69extern void dump_stack_regs(struct pt_regs *);
66 70
71/* Helper method for assembly dump_stack(). */
72extern void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52);
67 73
68#endif /* _ASM_TILE_STACK_H */ 74#endif /* _ASM_TILE_STACK_H */
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h
index 9f2b8e2f69d5..af165a74537f 100644
--- a/arch/tile/include/asm/syscalls.h
+++ b/arch/tile/include/asm/syscalls.h
@@ -22,7 +22,19 @@
22#include <linux/linkage.h> 22#include <linux/linkage.h>
23#include <linux/signal.h> 23#include <linux/signal.h>
24#include <linux/types.h> 24#include <linux/types.h>
25#include <asm-generic/syscalls.h> 25#include <linux/compat.h>
26
27/* The array of function pointers for syscalls. */
28extern void *sys_call_table[];
29#ifdef CONFIG_COMPAT
30extern void *compat_sys_call_table[];
31#endif
32
33/*
34 * Note that by convention, any syscall which requires the current
35 * register set takes an additional "struct pt_regs *" pointer; the
36 * sys_xxx() function just adds the pointer and tail-calls to _sys_xxx().
37 */
26 38
27/* kernel/sys.c */ 39/* kernel/sys.c */
28ssize_t sys32_readahead(int fd, u32 offset_lo, u32 offset_hi, u32 count); 40ssize_t sys32_readahead(int fd, u32 offset_lo, u32 offset_hi, u32 count);
@@ -31,10 +43,66 @@ long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi,
31int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, 43int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi,
32 u32 len_lo, u32 len_hi, int advice); 44 u32 len_lo, u32 len_hi, int advice);
33long sys_flush_cache(void); 45long sys_flush_cache(void);
46long sys_mmap2(unsigned long addr, unsigned long len,
47 unsigned long prot, unsigned long flags,
48 unsigned long fd, unsigned long pgoff);
49#ifdef __tilegx__
50long sys_mmap(unsigned long addr, unsigned long len,
51 unsigned long prot, unsigned long flags,
52 unsigned long fd, off_t pgoff);
53#endif
54
55/* kernel/process.c */
56long sys_clone(unsigned long clone_flags, unsigned long newsp,
57 void __user *parent_tid, void __user *child_tid);
58long _sys_clone(unsigned long clone_flags, unsigned long newsp,
59 void __user *parent_tid, void __user *child_tid,
60 struct pt_regs *regs);
61long sys_fork(void);
62long _sys_fork(struct pt_regs *regs);
63long sys_vfork(void);
64long _sys_vfork(struct pt_regs *regs);
65long sys_execve(char __user *filename, char __user * __user *argv,
66 char __user * __user *envp);
67long _sys_execve(char __user *filename, char __user * __user *argv,
68 char __user * __user *envp, struct pt_regs *regs);
69
70/* kernel/signal.c */
71long sys_sigaltstack(const stack_t __user *, stack_t __user *);
72long _sys_sigaltstack(const stack_t __user *, stack_t __user *,
73 struct pt_regs *);
74long sys_rt_sigreturn(void);
75long _sys_rt_sigreturn(struct pt_regs *regs);
76
77/* platform-independent functions */
78long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize);
79long sys_rt_sigaction(int sig, const struct sigaction __user *act,
80 struct sigaction __user *oact, size_t sigsetsize);
34 81
35#ifndef __tilegx__ 82#ifndef __tilegx__
36/* mm/fault.c */ 83/* mm/fault.c */
37int sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); 84int sys_cmpxchg_badaddr(unsigned long address);
85int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
86#endif
87
88#ifdef CONFIG_COMPAT
89long compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
90 compat_uptr_t __user *envp);
91long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
92 compat_uptr_t __user *envp, struct pt_regs *regs);
93long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
94 struct compat_sigaltstack __user *uoss_ptr);
95long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
96 struct compat_sigaltstack __user *uoss_ptr,
97 struct pt_regs *regs);
98long compat_sys_rt_sigreturn(void);
99long _compat_sys_rt_sigreturn(struct pt_regs *regs);
100
101/* These four are not defined for 64-bit, but serve as "compat" syscalls. */
102long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);
103long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
104long sys_truncate64(const char __user *path, loff_t length);
105long sys_ftruncate64(unsigned int fd, loff_t length);
38#endif 106#endif
39 107
40#endif /* _ASM_TILE_SYSCALLS_H */ 108#endif /* _ASM_TILE_SYSCALLS_H */
diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h
index d6ca7f816c87..0935094f370a 100644
--- a/arch/tile/include/asm/system.h
+++ b/arch/tile/include/asm/system.h
@@ -160,6 +160,14 @@ struct task_struct;
160extern struct task_struct *_switch_to(struct task_struct *prev, 160extern struct task_struct *_switch_to(struct task_struct *prev,
161 struct task_struct *next); 161 struct task_struct *next);
162 162
163/* Helper function for _switch_to(). */
164extern struct task_struct *__switch_to(struct task_struct *prev,
165 struct task_struct *next,
166 unsigned long new_system_save_1_0);
167
168/* Address that switched-away from tasks are at. */
169extern unsigned long get_switch_to_pc(void);
170
163/* 171/*
164 * On SMP systems, when the scheduler does migration-cost autodetection, 172 * On SMP systems, when the scheduler does migration-cost autodetection,
165 * it needs a way to flush as much of the CPU's caches as possible: 173 * it needs a way to flush as much of the CPU's caches as possible:
@@ -187,10 +195,26 @@ extern int unaligned_printk;
187/* Number of unaligned fixups performed */ 195/* Number of unaligned fixups performed */
188extern unsigned int unaligned_fixup_count; 196extern unsigned int unaligned_fixup_count;
189 197
198/* Init-time routine to do tile-specific per-cpu setup. */
199void setup_cpu(int boot);
200
190/* User-level DMA management functions */ 201/* User-level DMA management functions */
191void grant_dma_mpls(void); 202void grant_dma_mpls(void);
192void restrict_dma_mpls(void); 203void restrict_dma_mpls(void);
193 204
205#ifdef CONFIG_HARDWALL
206/* User-level network management functions */
207void reset_network_state(void);
208void grant_network_mpls(void);
209void restrict_network_mpls(void);
210int hardwall_deactivate(struct task_struct *task);
211
212/* Hook hardwall code into changes in affinity. */
213#define arch_set_cpus_allowed(p, new_mask) do { \
214 if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \
215 hardwall_deactivate(p); \
216} while (0)
217#endif
194 218
195/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */ 219/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */
196extern int _sim_syscall(int syscall_num, ...); 220extern int _sim_syscall(int syscall_num, ...);
@@ -215,6 +239,12 @@ extern int _sim_syscall(int syscall_num, ...);
215 homecache_migrate_kthread(); \ 239 homecache_migrate_kthread(); \
216} while (0) 240} while (0)
217 241
242/* Support function for forking a new task. */
243void ret_from_fork(void);
244
245/* Called from ret_from_fork() when a new process starts up. */
246struct task_struct *sim_notify_fork(struct task_struct *prev);
247
218#endif /* !__ASSEMBLY__ */ 248#endif /* !__ASSEMBLY__ */
219 249
220#endif /* _ASM_TILE_SYSTEM_H */ 250#endif /* _ASM_TILE_SYSTEM_H */
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h
index 9024bf3530aa..beec8729564a 100644
--- a/arch/tile/include/asm/thread_info.h
+++ b/arch/tile/include/asm/thread_info.h
@@ -55,7 +55,7 @@ struct thread_info {
55 .restart_block = { \ 55 .restart_block = { \
56 .fn = do_no_restart_syscall, \ 56 .fn = do_no_restart_syscall, \
57 }, \ 57 }, \
58 .step_state = 0, \ 58 .step_state = NULL, \
59} 59}
60 60
61#define init_thread_info (init_thread_union.thread_info) 61#define init_thread_info (init_thread_union.thread_info)
@@ -86,6 +86,12 @@ register unsigned long stack_pointer __asm__("sp");
86extern struct thread_info *alloc_thread_info(struct task_struct *task); 86extern struct thread_info *alloc_thread_info(struct task_struct *task);
87extern void free_thread_info(struct thread_info *info); 87extern void free_thread_info(struct thread_info *info);
88 88
89/* Sit on a nap instruction until interrupted. */
90extern void smp_nap(void);
91
92/* Enable interrupts racelessly and nap forever: helper for cpu_idle(). */
93extern void _cpu_idle(void);
94
89/* Switch boot idle thread to a freshly-allocated stack and free old stack. */ 95/* Switch boot idle thread to a freshly-allocated stack and free old stack. */
90extern void cpu_idle_on_new_stack(struct thread_info *old_ti, 96extern void cpu_idle_on_new_stack(struct thread_info *old_ti,
91 unsigned long new_sp, 97 unsigned long new_sp,
diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h
index eab33d4a917d..432a9c15c8a2 100644
--- a/arch/tile/include/asm/traps.h
+++ b/arch/tile/include/asm/traps.h
@@ -18,9 +18,28 @@
18/* mm/fault.c */ 18/* mm/fault.c */
19void do_page_fault(struct pt_regs *, int fault_num, 19void do_page_fault(struct pt_regs *, int fault_num,
20 unsigned long address, unsigned long write); 20 unsigned long address, unsigned long write);
21void do_async_page_fault(struct pt_regs *);
22
23#ifndef __tilegx__
24/*
25 * We return this structure in registers to avoid having to write
26 * additional save/restore code in the intvec.S caller.
27 */
28struct intvec_state {
29 void *handler;
30 unsigned long vecnum;
31 unsigned long fault_num;
32 unsigned long info;
33 unsigned long retval;
34};
35struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,
36 unsigned long address,
37 unsigned long info);
38#endif
21 39
22/* kernel/traps.c */ 40/* kernel/traps.c */
23void do_trap(struct pt_regs *, int fault_num, unsigned long reason); 41void do_trap(struct pt_regs *, int fault_num, unsigned long reason);
42void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52);
24 43
25/* kernel/time.c */ 44/* kernel/time.c */
26void do_timer_interrupt(struct pt_regs *, int fault_num); 45void do_timer_interrupt(struct pt_regs *, int fault_num);
@@ -31,6 +50,13 @@ void hv_message_intr(struct pt_regs *, int intnum);
31/* kernel/irq.c */ 50/* kernel/irq.c */
32void tile_dev_intr(struct pt_regs *, int intnum); 51void tile_dev_intr(struct pt_regs *, int intnum);
33 52
53#ifdef CONFIG_HARDWALL
54/* kernel/hardwall.c */
55void do_hardwall_trap(struct pt_regs *, int fault_num);
56#endif
57
58/* kernel/ptrace.c */
59void do_breakpoint(struct pt_regs *, int fault_num);
34 60
35 61
36#endif /* _ASM_TILE_SYSCALLS_H */ 62#endif /* _ASM_TILE_SYSCALLS_H */
diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h
index f3058afd5a88..ed17a80ec0ed 100644
--- a/arch/tile/include/asm/uaccess.h
+++ b/arch/tile/include/asm/uaccess.h
@@ -89,8 +89,10 @@ int __range_ok(unsigned long addr, unsigned long size);
89 * checks that the pointer is in the user space range - after calling 89 * checks that the pointer is in the user space range - after calling
90 * this function, memory access functions may still return -EFAULT. 90 * this function, memory access functions may still return -EFAULT.
91 */ 91 */
92#define access_ok(type, addr, size) \ 92#define access_ok(type, addr, size) ({ \
93 (likely(__range_ok((unsigned long)addr, size) == 0)) 93 __chk_user_ptr(addr); \
94 likely(__range_ok((unsigned long)(addr), (size)) == 0); \
95})
94 96
95/* 97/*
96 * The exception table consists of pairs of addresses: the first is the 98 * The exception table consists of pairs of addresses: the first is the
@@ -134,14 +136,14 @@ struct __get_user {
134 * such extended assembler routines, though we will have to use a 136 * such extended assembler routines, though we will have to use a
135 * different return code in that case (1, 2, or 4, rather than -EFAULT). 137 * different return code in that case (1, 2, or 4, rather than -EFAULT).
136 */ 138 */
137extern struct __get_user __get_user_1(const void *); 139extern struct __get_user __get_user_1(const void __user *);
138extern struct __get_user __get_user_2(const void *); 140extern struct __get_user __get_user_2(const void __user *);
139extern struct __get_user __get_user_4(const void *); 141extern struct __get_user __get_user_4(const void __user *);
140extern struct __get_user __get_user_8(const void *); 142extern struct __get_user __get_user_8(const void __user *);
141extern int __put_user_1(long, void *); 143extern int __put_user_1(long, void __user *);
142extern int __put_user_2(long, void *); 144extern int __put_user_2(long, void __user *);
143extern int __put_user_4(long, void *); 145extern int __put_user_4(long, void __user *);
144extern int __put_user_8(long long, void *); 146extern int __put_user_8(long long, void __user *);
145 147
146/* Unimplemented routines to cause linker failures */ 148/* Unimplemented routines to cause linker failures */
147extern struct __get_user __get_user_bad(void); 149extern struct __get_user __get_user_bad(void);
diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h
index 03b3d5d665dd..f2e3ff485333 100644
--- a/arch/tile/include/asm/unistd.h
+++ b/arch/tile/include/asm/unistd.h
@@ -15,7 +15,6 @@
15#if !defined(_ASM_TILE_UNISTD_H) || defined(__SYSCALL) 15#if !defined(_ASM_TILE_UNISTD_H) || defined(__SYSCALL)
16#define _ASM_TILE_UNISTD_H 16#define _ASM_TILE_UNISTD_H
17 17
18
19#ifndef __LP64__ 18#ifndef __LP64__
20/* Use the flavor of this syscall that matches the 32-bit API better. */ 19/* Use the flavor of this syscall that matches the 32-bit API better. */
21#define __ARCH_WANT_SYNC_FILE_RANGE2 20#define __ARCH_WANT_SYNC_FILE_RANGE2
@@ -24,6 +23,10 @@
24/* Use the standard ABI for syscalls. */ 23/* Use the standard ABI for syscalls. */
25#include <asm-generic/unistd.h> 24#include <asm-generic/unistd.h>
26 25
26/* Additional Tilera-specific syscalls. */
27#define __NR_flush_cache (__NR_arch_specific_syscall + 1)
28__SYSCALL(__NR_flush_cache, sys_flush_cache)
29
27#ifndef __tilegx__ 30#ifndef __tilegx__
28/* "Fast" syscalls provide atomic support for 32-bit chips. */ 31/* "Fast" syscalls provide atomic support for 32-bit chips. */
29#define __NR_FAST_cmpxchg -1 32#define __NR_FAST_cmpxchg -1
@@ -33,10 +36,6 @@
33__SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr) 36__SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr)
34#endif 37#endif
35 38
36/* Additional Tilera-specific syscalls. */
37#define __NR_flush_cache (__NR_arch_specific_syscall + 1)
38__SYSCALL(__NR_flush_cache, sys_flush_cache)
39
40#ifdef __KERNEL__ 39#ifdef __KERNEL__
41/* In compat mode, we use sys_llseek() for compat_sys_llseek(). */ 40/* In compat mode, we use sys_llseek() for compat_sys_llseek(). */
42#ifdef CONFIG_COMPAT 41#ifdef CONFIG_COMPAT