• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * This file contains various random system calls that
3   * have a non-standard calling sequence on the Linux/Meta
4   * platform.
5   */
6  
7  #include <linux/errno.h>
8  #include <linux/sched.h>
9  #include <linux/mm.h>
10  #include <linux/syscalls.h>
11  #include <linux/mman.h>
12  #include <linux/file.h>
13  #include <linux/fs.h>
14  #include <linux/uaccess.h>
15  #include <linux/unistd.h>
16  #include <asm/cacheflush.h>
17  #include <asm/core_reg.h>
18  #include <asm/global_lock.h>
19  #include <asm/switch.h>
20  #include <asm/syscall.h>
21  #include <asm/syscalls.h>
22  #include <asm/user_gateway.h>
23  
24  #define merge_64(hi, lo) ((((unsigned long long)(hi)) << 32) + \
25  			  ((lo) & 0xffffffffUL))
26  
metag_mmap_check(unsigned long addr,unsigned long len,unsigned long flags)27  int metag_mmap_check(unsigned long addr, unsigned long len,
28  		     unsigned long flags)
29  {
30  	/* We can't have people trying to write to the bottom of the
31  	 * memory map, there are mysterious unspecified things there that
32  	 * we don't want people trampling on.
33  	 */
34  	if ((flags & MAP_FIXED) && (addr < TASK_UNMAPPED_BASE))
35  		return -EINVAL;
36  
37  	return 0;
38  }
39  
sys_mmap2(unsigned long addr,unsigned long len,unsigned long prot,unsigned long flags,unsigned long fd,unsigned long pgoff)40  asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
41  			  unsigned long prot, unsigned long flags,
42  			  unsigned long fd, unsigned long pgoff)
43  {
44  	/* The shift for mmap2 is constant, regardless of PAGE_SIZE setting. */
45  	if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
46  		return -EINVAL;
47  
48  	pgoff >>= PAGE_SHIFT - 12;
49  
50  	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
51  }
52  
sys_metag_setglobalbit(char __user * addr,int mask)53  asmlinkage int sys_metag_setglobalbit(char __user *addr, int mask)
54  {
55  	char tmp;
56  	int ret = 0;
57  	unsigned int flags;
58  
59  	if (!((__force unsigned int)addr >= LINCORE_BASE))
60  		return -EFAULT;
61  
62  	__global_lock2(flags);
63  
64  	metag_data_cache_flush((__force void *)addr, sizeof(mask));
65  
66  	ret = __get_user(tmp, addr);
67  	if (ret)
68  		goto out;
69  	tmp |= mask;
70  	ret = __put_user(tmp, addr);
71  
72  	metag_data_cache_flush((__force void *)addr, sizeof(mask));
73  
74  out:
75  	__global_unlock2(flags);
76  
77  	return ret;
78  }
79  
80  #define TXDEFR_FPU_MASK ((0x1f << 16) | 0x1f)
81  
sys_metag_set_fpu_flags(unsigned int flags)82  asmlinkage void sys_metag_set_fpu_flags(unsigned int flags)
83  {
84  	unsigned int temp;
85  
86  	flags &= TXDEFR_FPU_MASK;
87  
88  	temp = __core_reg_get(TXDEFR);
89  	temp &= ~TXDEFR_FPU_MASK;
90  	temp |= flags;
91  	__core_reg_set(TXDEFR, temp);
92  }
93  
sys_metag_set_tls(void __user * ptr)94  asmlinkage int sys_metag_set_tls(void __user *ptr)
95  {
96  	current->thread.tls_ptr = ptr;
97  	set_gateway_tls(ptr);
98  
99  	return 0;
100  }
101  
sys_metag_get_tls(void)102  asmlinkage void *sys_metag_get_tls(void)
103  {
104  	return (__force void *)current->thread.tls_ptr;
105  }
106  
sys_truncate64_metag(const char __user * path,unsigned long lo,unsigned long hi)107  asmlinkage long sys_truncate64_metag(const char __user *path, unsigned long lo,
108  				     unsigned long hi)
109  {
110  	return sys_truncate64(path, merge_64(hi, lo));
111  }
112  
sys_ftruncate64_metag(unsigned int fd,unsigned long lo,unsigned long hi)113  asmlinkage long sys_ftruncate64_metag(unsigned int fd, unsigned long lo,
114  				      unsigned long hi)
115  {
116  	return sys_ftruncate64(fd, merge_64(hi, lo));
117  }
118  
sys_fadvise64_64_metag(int fd,unsigned long offs_lo,unsigned long offs_hi,unsigned long len_lo,unsigned long len_hi,int advice)119  asmlinkage long sys_fadvise64_64_metag(int fd, unsigned long offs_lo,
120  				       unsigned long offs_hi,
121  				       unsigned long len_lo,
122  				       unsigned long len_hi, int advice)
123  {
124  	return sys_fadvise64_64(fd, merge_64(offs_hi, offs_lo),
125  				merge_64(len_hi, len_lo), advice);
126  }
127  
sys_readahead_metag(int fd,unsigned long lo,unsigned long hi,size_t count)128  asmlinkage long sys_readahead_metag(int fd, unsigned long lo, unsigned long hi,
129  				    size_t count)
130  {
131  	return sys_readahead(fd, merge_64(hi, lo), count);
132  }
133  
sys_pread64_metag(unsigned long fd,char __user * buf,size_t count,unsigned long lo,unsigned long hi)134  asmlinkage ssize_t sys_pread64_metag(unsigned long fd, char __user *buf,
135  				     size_t count, unsigned long lo,
136  				     unsigned long hi)
137  {
138  	return sys_pread64(fd, buf, count, merge_64(hi, lo));
139  }
140  
sys_pwrite64_metag(unsigned long fd,char __user * buf,size_t count,unsigned long lo,unsigned long hi)141  asmlinkage ssize_t sys_pwrite64_metag(unsigned long fd, char __user *buf,
142  				      size_t count, unsigned long lo,
143  				      unsigned long hi)
144  {
145  	return sys_pwrite64(fd, buf, count, merge_64(hi, lo));
146  }
147  
sys_sync_file_range_metag(int fd,unsigned long offs_lo,unsigned long offs_hi,unsigned long len_lo,unsigned long len_hi,unsigned int flags)148  asmlinkage long sys_sync_file_range_metag(int fd, unsigned long offs_lo,
149  					  unsigned long offs_hi,
150  					  unsigned long len_lo,
151  					  unsigned long len_hi,
152  					  unsigned int flags)
153  {
154  	return sys_sync_file_range(fd, merge_64(offs_hi, offs_lo),
155  				   merge_64(len_hi, len_lo), flags);
156  }
157  
158  /* Provide the actual syscall number to call mapping. */
159  #undef __SYSCALL
160  #define __SYSCALL(nr, call) [nr] = (call),
161  
162  /*
163   * We need wrappers for anything with unaligned 64bit arguments
164   */
165  #define sys_truncate64		sys_truncate64_metag
166  #define sys_ftruncate64		sys_ftruncate64_metag
167  #define sys_fadvise64_64	sys_fadvise64_64_metag
168  #define sys_readahead		sys_readahead_metag
169  #define sys_pread64		sys_pread64_metag
170  #define sys_pwrite64		sys_pwrite64_metag
171  #define sys_sync_file_range	sys_sync_file_range_metag
172  
173  /*
174   * Note that we can't include <linux/unistd.h> here since the header
175   * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
176   */
177  const void *sys_call_table[__NR_syscalls] = {
178  	[0 ... __NR_syscalls-1] = sys_ni_syscall,
179  #include <asm/unistd.h>
180  };
181