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