| author | |
| committer | |
| log | 503b03daa30bfcebbd45f27feff87f74b11b45a6 |
| tree | a18e7aa51632de8924d2011a1c338dbc36560993 |
| parent | 95d4703bee77ead0bc21f3cf8ca4c09edeba6bd4 |
On MIPS, $a3 ($7) carries the fourth argument [1] and returns the
kernel's error flag [2]. The kernel writes the flag on every return,
success included [3]. syscall4 and up declared $7 an input only, so
the compiler assumed it still held the argument after the syscall.
In release builds, a pointer passed as the fourth argument then reads
back as the flag, 0 on success, and using it faults at address 0.
Commit 5b29b4ffa6 ("Fix MIPS inline assembly clobbers") took $7 out of
the clobbers, since an input cannot be one, but never made it an
output.
Add that output, as alpha.zig does for its argument registers [4]
and musl does with "+r" [5]. $7 stays out of the clobbers, because a
register that is input, output and clobber at once can miscompile (#35724).
[1] - https://refspecs.linuxfoundation.org/elf/mipsabi.pdf#page=24
[2] - https://man7.org/linux/man-pages/man2/syscall.2.html
[3] - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/mips/kernel/scall32-o32.S?h=v7.1#n112
[4] - https://codeberg.org/ziglang/zig/src/commit/d8938120130dbe48ee8764b502b18c6224ab9340/lib/std/os/linux/alpha.zig#L38-L46
[5] - https://git.musl-libc.org/cgit/musl/tree/arch/mips/syscall_arch.h?h=v1.2.6#n81
closes #372473 files changed, 30 insertions(+), 0 deletions(-)
lib/std/os/linux/mips.zig+12| ... | @@ -75,12 +75,15 @@ pub fn syscall4( | ... | @@ -75,12 +75,15 @@ pub fn syscall4( |
| 75 | arg3: syscall_arg_t, | 75 | arg3: syscall_arg_t, |
| 76 | arg4: syscall_arg_t, | 76 | arg4: syscall_arg_t, |
| 77 | ) u32 { | 77 | ) u32 { |
| 78 | // $7 is both an input and a clobber. | ||
| 79 | var r7_out: syscall_arg_t = undefined; | ||
| 78 | return asm volatile ( | 80 | return asm volatile ( |
| 79 | \\ syscall | 81 | \\ syscall |
| 80 | \\ beq $a3, $zero, 1f | 82 | \\ beq $a3, $zero, 1f |
| 81 | \\ subu $v0, $zero, $v0 | 83 | \\ subu $v0, $zero, $v0 |
| 82 | \\1: | 84 | \\1: |
| 83 | : [ret] "={$2}" (-> u32), | 85 | : [ret] "={$2}" (-> u32), |
| 86 | [r7_out] "={$7}" (r7_out), | ||
| 84 | : [number] "{$2}" (@backingInt(number)), | 87 | : [number] "{$2}" (@backingInt(number)), |
| 85 | [arg1] "{$4}" (arg1), | 88 | [arg1] "{$4}" (arg1), |
| 86 | [arg2] "{$5}" (arg2), | 89 | [arg2] "{$5}" (arg2), |
| ... | @@ -100,6 +103,8 @@ pub fn syscall5( | ... | @@ -100,6 +103,8 @@ pub fn syscall5( |
| 100 | arg4: syscall_arg_t, | 103 | arg4: syscall_arg_t, |
| 101 | arg5: syscall_arg_t, | 104 | arg5: syscall_arg_t, |
| 102 | ) u32 { | 105 | ) u32 { |
| 106 | // $7 is both an input and a clobber. | ||
| 107 | var r7_out: syscall_arg_t = undefined; | ||
| 103 | return asm volatile ( | 108 | return asm volatile ( |
| 104 | \\ subu $sp, $sp, 24 | 109 | \\ subu $sp, $sp, 24 |
| 105 | \\ sw %[arg5], 16($sp) | 110 | \\ sw %[arg5], 16($sp) |
| ... | @@ -109,6 +114,7 @@ pub fn syscall5( | ... | @@ -109,6 +114,7 @@ pub fn syscall5( |
| 109 | \\ subu $v0, $zero, $v0 | 114 | \\ subu $v0, $zero, $v0 |
| 110 | \\1: | 115 | \\1: |
| 111 | : [ret] "={$2}" (-> u32), | 116 | : [ret] "={$2}" (-> u32), |
| 117 | [r7_out] "={$7}" (r7_out), | ||
| 112 | : [number] "{$2}" (@backingInt(number)), | 118 | : [number] "{$2}" (@backingInt(number)), |
| 113 | [arg1] "{$4}" (arg1), | 119 | [arg1] "{$4}" (arg1), |
| 114 | [arg2] "{$5}" (arg2), | 120 | [arg2] "{$5}" (arg2), |
| ... | @@ -127,6 +133,8 @@ pub fn syscall6( | ... | @@ -127,6 +133,8 @@ pub fn syscall6( |
| 127 | arg5: syscall_arg_t, | 133 | arg5: syscall_arg_t, |
| 128 | arg6: syscall_arg_t, | 134 | arg6: syscall_arg_t, |
| 129 | ) u32 { | 135 | ) u32 { |
| 136 | // $7 is both an input and a clobber. | ||
| 137 | var r7_out: syscall_arg_t = undefined; | ||
| 130 | return asm volatile ( | 138 | return asm volatile ( |
| 131 | \\ subu $sp, $sp, 24 | 139 | \\ subu $sp, $sp, 24 |
| 132 | \\ sw %[arg5], 16($sp) | 140 | \\ sw %[arg5], 16($sp) |
| ... | @@ -137,6 +145,7 @@ pub fn syscall6( | ... | @@ -137,6 +145,7 @@ pub fn syscall6( |
| 137 | \\ subu $v0, $zero, $v0 | 145 | \\ subu $v0, $zero, $v0 |
| 138 | \\1: | 146 | \\1: |
| 139 | : [ret] "={$2}" (-> u32), | 147 | : [ret] "={$2}" (-> u32), |
| 148 | [r7_out] "={$7}" (r7_out), | ||
| 140 | : [number] "{$2}" (@backingInt(number)), | 149 | : [number] "{$2}" (@backingInt(number)), |
| 141 | [arg1] "{$4}" (arg1), | 150 | [arg1] "{$4}" (arg1), |
| 142 | [arg2] "{$5}" (arg2), | 151 | [arg2] "{$5}" (arg2), |
| ... | @@ -157,6 +166,8 @@ pub fn syscall7( | ... | @@ -157,6 +166,8 @@ pub fn syscall7( |
| 157 | arg6: syscall_arg_t, | 166 | arg6: syscall_arg_t, |
| 158 | arg7: syscall_arg_t, | 167 | arg7: syscall_arg_t, |
| 159 | ) u32 { | 168 | ) u32 { |
| 169 | // $7 is both an input and a clobber. | ||
| 170 | var r7_out: syscall_arg_t = undefined; | ||
| 160 | return asm volatile ( | 171 | return asm volatile ( |
| 161 | \\ subu $sp, $sp, 32 | 172 | \\ subu $sp, $sp, 32 |
| 162 | \\ sw %[arg5], 16($sp) | 173 | \\ sw %[arg5], 16($sp) |
| ... | @@ -168,6 +179,7 @@ pub fn syscall7( | ... | @@ -168,6 +179,7 @@ pub fn syscall7( |
| 168 | \\ subu $v0, $zero, $v0 | 179 | \\ subu $v0, $zero, $v0 |
| 169 | \\1: | 180 | \\1: |
| 170 | : [ret] "={$2}" (-> u32), | 181 | : [ret] "={$2}" (-> u32), |
| 182 | [r7_out] "={$7}" (r7_out), | ||
| 171 | : [number] "{$2}" (@backingInt(number)), | 183 | : [number] "{$2}" (@backingInt(number)), |
| 172 | [arg1] "{$4}" (arg1), | 184 | [arg1] "{$4}" (arg1), |
| 173 | [arg2] "{$5}" (arg2), | 185 | [arg2] "{$5}" (arg2), |
lib/std/os/linux/mips64.zig+9| ... | @@ -75,12 +75,15 @@ pub fn syscall4( | ... | @@ -75,12 +75,15 @@ pub fn syscall4( |
| 75 | arg3: syscall_arg_t, | 75 | arg3: syscall_arg_t, |
| 76 | arg4: syscall_arg_t, | 76 | arg4: syscall_arg_t, |
| 77 | ) u64 { | 77 | ) u64 { |
| 78 | // $7 is both an input and a clobber. | ||
| 79 | var r7_out: syscall_arg_t = undefined; | ||
| 78 | return asm volatile ( | 80 | return asm volatile ( |
| 79 | \\ syscall | 81 | \\ syscall |
| 80 | \\ beq $a3, $zero, 1f | 82 | \\ beq $a3, $zero, 1f |
| 81 | \\ dsubu $v0, $zero, $v0 | 83 | \\ dsubu $v0, $zero, $v0 |
| 82 | \\1: | 84 | \\1: |
| 83 | : [ret] "={$2}" (-> u64), | 85 | : [ret] "={$2}" (-> u64), |
| 86 | [r7_out] "={$7}" (r7_out), | ||
| 84 | : [number] "{$2}" (@backingInt(number)), | 87 | : [number] "{$2}" (@backingInt(number)), |
| 85 | [arg1] "{$4}" (arg1), | 88 | [arg1] "{$4}" (arg1), |
| 86 | [arg2] "{$5}" (arg2), | 89 | [arg2] "{$5}" (arg2), |
| ... | @@ -97,12 +100,15 @@ pub fn syscall5( | ... | @@ -97,12 +100,15 @@ pub fn syscall5( |
| 97 | arg4: syscall_arg_t, | 100 | arg4: syscall_arg_t, |
| 98 | arg5: syscall_arg_t, | 101 | arg5: syscall_arg_t, |
| 99 | ) u64 { | 102 | ) u64 { |
| 103 | // $7 is both an input and a clobber. | ||
| 104 | var r7_out: syscall_arg_t = undefined; | ||
| 100 | return asm volatile ( | 105 | return asm volatile ( |
| 101 | \\ syscall | 106 | \\ syscall |
| 102 | \\ beq $a3, $zero, 1f | 107 | \\ beq $a3, $zero, 1f |
| 103 | \\ dsubu $v0, $zero, $v0 | 108 | \\ dsubu $v0, $zero, $v0 |
| 104 | \\1: | 109 | \\1: |
| 105 | : [ret] "={$2}" (-> u64), | 110 | : [ret] "={$2}" (-> u64), |
| 111 | [r7_out] "={$7}" (r7_out), | ||
| 106 | : [number] "{$2}" (@backingInt(number)), | 112 | : [number] "{$2}" (@backingInt(number)), |
| 107 | [arg1] "{$4}" (arg1), | 113 | [arg1] "{$4}" (arg1), |
| 108 | [arg2] "{$5}" (arg2), | 114 | [arg2] "{$5}" (arg2), |
| ... | @@ -121,12 +127,15 @@ pub fn syscall6( | ... | @@ -121,12 +127,15 @@ pub fn syscall6( |
| 121 | arg5: syscall_arg_t, | 127 | arg5: syscall_arg_t, |
| 122 | arg6: syscall_arg_t, | 128 | arg6: syscall_arg_t, |
| 123 | ) u64 { | 129 | ) u64 { |
| 130 | // $7 is both an input and a clobber. | ||
| 131 | var r7_out: syscall_arg_t = undefined; | ||
| 124 | return asm volatile ( | 132 | return asm volatile ( |
| 125 | \\ syscall | 133 | \\ syscall |
| 126 | \\ beq $a3, $zero, 1f | 134 | \\ beq $a3, $zero, 1f |
| 127 | \\ dsubu $v0, $zero, $v0 | 135 | \\ dsubu $v0, $zero, $v0 |
| 128 | \\1: | 136 | \\1: |
| 129 | : [ret] "={$2}" (-> u64), | 137 | : [ret] "={$2}" (-> u64), |
| 138 | [r7_out] "={$7}" (r7_out), | ||
| 130 | : [number] "{$2}" (@backingInt(number)), | 139 | : [number] "{$2}" (@backingInt(number)), |
| 131 | [arg1] "{$4}" (arg1), | 140 | [arg1] "{$4}" (arg1), |
| 132 | [arg2] "{$5}" (arg2), | 141 | [arg2] "{$5}" (arg2), |
lib/std/os/linux/mipsn32.zig+9| ... | @@ -75,12 +75,15 @@ pub fn syscall4( | ... | @@ -75,12 +75,15 @@ pub fn syscall4( |
| 75 | arg3: syscall_arg_t, | 75 | arg3: syscall_arg_t, |
| 76 | arg4: syscall_arg_t, | 76 | arg4: syscall_arg_t, |
| 77 | ) u32 { | 77 | ) u32 { |
| 78 | // $7 is both an input and a clobber. | ||
| 79 | var r7_out: syscall_arg_t = undefined; | ||
| 78 | return asm volatile ( | 80 | return asm volatile ( |
| 79 | \\ syscall | 81 | \\ syscall |
| 80 | \\ beq $a3, $zero, 1f | 82 | \\ beq $a3, $zero, 1f |
| 81 | \\ subu $v0, $zero, $v0 | 83 | \\ subu $v0, $zero, $v0 |
| 82 | \\1: | 84 | \\1: |
| 83 | : [ret] "={$2}" (-> u32), | 85 | : [ret] "={$2}" (-> u32), |
| 86 | [r7_out] "={$7}" (r7_out), | ||
| 84 | : [number] "{$2}" (@backingInt(number)), | 87 | : [number] "{$2}" (@backingInt(number)), |
| 85 | [arg1] "{$4}" (arg1), | 88 | [arg1] "{$4}" (arg1), |
| 86 | [arg2] "{$5}" (arg2), | 89 | [arg2] "{$5}" (arg2), |
| ... | @@ -97,12 +100,15 @@ pub fn syscall5( | ... | @@ -97,12 +100,15 @@ pub fn syscall5( |
| 97 | arg4: syscall_arg_t, | 100 | arg4: syscall_arg_t, |
| 98 | arg5: syscall_arg_t, | 101 | arg5: syscall_arg_t, |
| 99 | ) u32 { | 102 | ) u32 { |
| 103 | // $7 is both an input and a clobber. | ||
| 104 | var r7_out: syscall_arg_t = undefined; | ||
| 100 | return asm volatile ( | 105 | return asm volatile ( |
| 101 | \\ syscall | 106 | \\ syscall |
| 102 | \\ beq $a3, $zero, 1f | 107 | \\ beq $a3, $zero, 1f |
| 103 | \\ subu $v0, $zero, $v0 | 108 | \\ subu $v0, $zero, $v0 |
| 104 | \\1: | 109 | \\1: |
| 105 | : [ret] "={$2}" (-> u32), | 110 | : [ret] "={$2}" (-> u32), |
| 111 | [r7_out] "={$7}" (r7_out), | ||
| 106 | : [number] "{$2}" (@backingInt(number)), | 112 | : [number] "{$2}" (@backingInt(number)), |
| 107 | [arg1] "{$4}" (arg1), | 113 | [arg1] "{$4}" (arg1), |
| 108 | [arg2] "{$5}" (arg2), | 114 | [arg2] "{$5}" (arg2), |
| ... | @@ -121,12 +127,15 @@ pub fn syscall6( | ... | @@ -121,12 +127,15 @@ pub fn syscall6( |
| 121 | arg5: syscall_arg_t, | 127 | arg5: syscall_arg_t, |
| 122 | arg6: syscall_arg_t, | 128 | arg6: syscall_arg_t, |
| 123 | ) u32 { | 129 | ) u32 { |
| 130 | // $7 is both an input and a clobber. | ||
| 131 | var r7_out: syscall_arg_t = undefined; | ||
| 124 | return asm volatile ( | 132 | return asm volatile ( |
| 125 | \\ syscall | 133 | \\ syscall |
| 126 | \\ beq $a3, $zero, 1f | 134 | \\ beq $a3, $zero, 1f |
| 127 | \\ subu $v0, $zero, $v0 | 135 | \\ subu $v0, $zero, $v0 |
| 128 | \\1: | 136 | \\1: |
| 129 | : [ret] "={$2}" (-> u32), | 137 | : [ret] "={$2}" (-> u32), |
| 138 | [r7_out] "={$7}" (r7_out), | ||
| 130 | : [number] "{$2}" (@backingInt(number)), | 139 | : [number] "{$2}" (@backingInt(number)), |
| 131 | [arg1] "{$4}" (arg1), | 140 | [arg1] "{$4}" (arg1), |
| 132 | [arg2] "{$5}" (arg2), | 141 | [arg2] "{$5}" (arg2), |