1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * sys_ppc32.c: 32-bit system calls with complex calling conventions. |
4 | * |
5 | * Copyright (C) 2001 IBM |
6 | * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) |
7 | * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) |
8 | * |
9 | * 32-bit system calls with 64-bit arguments pass those in register pairs. |
10 | * This must be specially dealt with on 64-bit kernels. The compat_arg_u64_dual |
11 | * in generic compat syscalls is not always usable because the register |
12 | * pairing is constrained depending on preceding arguments. |
13 | * |
14 | * An analogous problem exists on 32-bit kernels with ARCH_HAS_SYSCALL_WRAPPER, |
15 | * the defined system call functions take the pt_regs as an argument, and there |
16 | * is a mapping macro which maps registers to arguments |
17 | * (SC_POWERPC_REGS_TO_ARGS) which also does not deal with these 64-bit |
18 | * arguments. |
19 | * |
20 | * This file contains these system calls. |
21 | */ |
22 | |
23 | #include <linux/kernel.h> |
24 | #include <linux/sched.h> |
25 | #include <linux/fs.h> |
26 | #include <linux/mm.h> |
27 | #include <linux/file.h> |
28 | #include <linux/signal.h> |
29 | #include <linux/resource.h> |
30 | #include <linux/times.h> |
31 | #include <linux/smp.h> |
32 | #include <linux/sem.h> |
33 | #include <linux/msg.h> |
34 | #include <linux/shm.h> |
35 | #include <linux/poll.h> |
36 | #include <linux/personality.h> |
37 | #include <linux/stat.h> |
38 | #include <linux/in.h> |
39 | #include <linux/syscalls.h> |
40 | #include <linux/unistd.h> |
41 | #include <linux/sysctl.h> |
42 | #include <linux/binfmts.h> |
43 | #include <linux/security.h> |
44 | #include <linux/compat.h> |
45 | #include <linux/ptrace.h> |
46 | #include <linux/elf.h> |
47 | #include <linux/ipc.h> |
48 | #include <linux/slab.h> |
49 | |
50 | #include <asm/ptrace.h> |
51 | #include <asm/types.h> |
52 | #include <linux/uaccess.h> |
53 | #include <asm/unistd.h> |
54 | #include <asm/time.h> |
55 | #include <asm/mmu_context.h> |
56 | #include <asm/ppc-pci.h> |
57 | #include <asm/syscalls.h> |
58 | #include <asm/switch_to.h> |
59 | |
60 | #ifdef CONFIG_PPC32 |
61 | #define PPC32_SYSCALL_DEFINE4 SYSCALL_DEFINE4 |
62 | #define PPC32_SYSCALL_DEFINE5 SYSCALL_DEFINE5 |
63 | #define PPC32_SYSCALL_DEFINE6 SYSCALL_DEFINE6 |
64 | #else |
65 | #define PPC32_SYSCALL_DEFINE4 COMPAT_SYSCALL_DEFINE4 |
66 | #define PPC32_SYSCALL_DEFINE5 COMPAT_SYSCALL_DEFINE5 |
67 | #define PPC32_SYSCALL_DEFINE6 COMPAT_SYSCALL_DEFINE6 |
68 | #endif |
69 | |
70 | PPC32_SYSCALL_DEFINE6(ppc_pread64, |
71 | unsigned int, fd, |
72 | char __user *, ubuf, compat_size_t, count, |
73 | u32, reg6, u32, pos1, u32, pos2) |
74 | { |
75 | return ksys_pread64(fd, buf: ubuf, count, pos: merge_64(pos1, pos2)); |
76 | } |
77 | |
78 | PPC32_SYSCALL_DEFINE6(ppc_pwrite64, |
79 | unsigned int, fd, |
80 | const char __user *, ubuf, compat_size_t, count, |
81 | u32, reg6, u32, pos1, u32, pos2) |
82 | { |
83 | return ksys_pwrite64(fd, buf: ubuf, count, pos: merge_64(pos1, pos2)); |
84 | } |
85 | |
86 | PPC32_SYSCALL_DEFINE5(ppc_readahead, |
87 | int, fd, u32, r4, |
88 | u32, offset1, u32, offset2, u32, count) |
89 | { |
90 | return ksys_readahead(fd, offset: merge_64(offset1, offset2), count); |
91 | } |
92 | |
93 | PPC32_SYSCALL_DEFINE4(ppc_truncate64, |
94 | const char __user *, path, u32, reg4, |
95 | unsigned long, len1, unsigned long, len2) |
96 | { |
97 | return ksys_truncate(pathname: path, length: merge_64(len1, len2)); |
98 | } |
99 | |
100 | PPC32_SYSCALL_DEFINE4(ppc_ftruncate64, |
101 | unsigned int, fd, u32, reg4, |
102 | unsigned long, len1, unsigned long, len2) |
103 | { |
104 | return ksys_ftruncate(fd, length: merge_64(len1, len2)); |
105 | } |
106 | |
107 | PPC32_SYSCALL_DEFINE6(ppc32_fadvise64, |
108 | int, fd, u32, unused, u32, offset1, u32, offset2, |
109 | size_t, len, int, advice) |
110 | { |
111 | return ksys_fadvise64_64(fd, offset: merge_64(offset1, offset2), len, |
112 | advice); |
113 | } |
114 | |
115 | PPC32_SYSCALL_DEFINE6(ppc_sync_file_range2, |
116 | int, fd, unsigned int, flags, |
117 | unsigned int, offset1, unsigned int, offset2, |
118 | unsigned int, nbytes1, unsigned int, nbytes2) |
119 | { |
120 | loff_t offset = merge_64(offset1, offset2); |
121 | loff_t nbytes = merge_64(nbytes1, nbytes2); |
122 | |
123 | return ksys_sync_file_range(fd, offset, nbytes, flags); |
124 | } |
125 | |
126 | #ifdef CONFIG_PPC32 |
127 | SYSCALL_DEFINE6(ppc_fallocate, |
128 | int, fd, int, mode, |
129 | u32, offset1, u32, offset2, u32, len1, u32, len2) |
130 | { |
131 | return ksys_fallocate(fd, mode, |
132 | merge_64(offset1, offset2), |
133 | merge_64(len1, len2)); |
134 | } |
135 | #endif |
136 | |