1// Copyright 2020 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:build openbsd && !mips64 6 7package runtime 8 9import ( 10 "internal/abi" 11 "internal/runtime/atomic" 12 "unsafe" 13) 14 15// This is exported via linkname to assembly in runtime/cgo. 16// 17//go:linkname exit 18//go:nosplit 19//go:cgo_unsafe_args 20func exit(code int32) { 21 libcCall(unsafe.Pointer(abi.FuncPCABI0(exit_trampoline)), unsafe.Pointer(&code)) 22} 23func exit_trampoline() 24 25//go:nosplit 26//go:cgo_unsafe_args 27func getthrid() (tid int32) { 28 libcCall(unsafe.Pointer(abi.FuncPCABI0(getthrid_trampoline)), unsafe.Pointer(&tid)) 29 return 30} 31func getthrid_trampoline() 32 33//go:nosplit 34//go:cgo_unsafe_args 35func raiseproc(sig uint32) { 36 libcCall(unsafe.Pointer(abi.FuncPCABI0(raiseproc_trampoline)), unsafe.Pointer(&sig)) 37} 38func raiseproc_trampoline() 39 40//go:nosplit 41//go:cgo_unsafe_args 42func thrkill(tid int32, sig int) { 43 libcCall(unsafe.Pointer(abi.FuncPCABI0(thrkill_trampoline)), unsafe.Pointer(&tid)) 44} 45func thrkill_trampoline() 46 47// mmap is used to do low-level memory allocation via mmap. Don't allow stack 48// splits, since this function (used by sysAlloc) is called in a lot of low-level 49// parts of the runtime and callers often assume it won't acquire any locks. 50// 51//go:nosplit 52func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) { 53 args := struct { 54 addr unsafe.Pointer 55 n uintptr 56 prot, flags, fd int32 57 off uint32 58 ret1 unsafe.Pointer 59 ret2 int 60 }{addr, n, prot, flags, fd, off, nil, 0} 61 libcCall(unsafe.Pointer(abi.FuncPCABI0(mmap_trampoline)), unsafe.Pointer(&args)) 62 KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. 63 return args.ret1, args.ret2 64} 65func mmap_trampoline() 66 67//go:nosplit 68//go:cgo_unsafe_args 69func munmap(addr unsafe.Pointer, n uintptr) { 70 libcCall(unsafe.Pointer(abi.FuncPCABI0(munmap_trampoline)), unsafe.Pointer(&addr)) 71 KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. 72} 73func munmap_trampoline() 74 75//go:nosplit 76//go:cgo_unsafe_args 77func madvise(addr unsafe.Pointer, n uintptr, flags int32) { 78 libcCall(unsafe.Pointer(abi.FuncPCABI0(madvise_trampoline)), unsafe.Pointer(&addr)) 79 KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. 80} 81func madvise_trampoline() 82 83//go:nosplit 84//go:cgo_unsafe_args 85func open(name *byte, mode, perm int32) (ret int32) { 86 ret = libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) 87 KeepAlive(name) 88 return 89} 90func open_trampoline() 91 92//go:nosplit 93//go:cgo_unsafe_args 94func closefd(fd int32) int32 { 95 return libcCall(unsafe.Pointer(abi.FuncPCABI0(close_trampoline)), unsafe.Pointer(&fd)) 96} 97func close_trampoline() 98 99//go:nosplit 100//go:cgo_unsafe_args 101func read(fd int32, p unsafe.Pointer, n int32) int32 { 102 ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(read_trampoline)), unsafe.Pointer(&fd)) 103 KeepAlive(p) 104 return ret 105} 106func read_trampoline() 107 108//go:nosplit 109//go:cgo_unsafe_args 110func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { 111 ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) 112 KeepAlive(p) 113 return ret 114} 115func write_trampoline() 116 117func pipe2(flags int32) (r, w int32, errno int32) { 118 var p [2]int32 119 args := struct { 120 p unsafe.Pointer 121 flags int32 122 }{noescape(unsafe.Pointer(&p)), flags} 123 errno = libcCall(unsafe.Pointer(abi.FuncPCABI0(pipe2_trampoline)), unsafe.Pointer(&args)) 124 return p[0], p[1], errno 125} 126func pipe2_trampoline() 127 128//go:nosplit 129//go:cgo_unsafe_args 130func setitimer(mode int32, new, old *itimerval) { 131 libcCall(unsafe.Pointer(abi.FuncPCABI0(setitimer_trampoline)), unsafe.Pointer(&mode)) 132 KeepAlive(new) 133 KeepAlive(old) 134} 135func setitimer_trampoline() 136 137//go:nosplit 138//go:cgo_unsafe_args 139func usleep(usec uint32) { 140 libcCall(unsafe.Pointer(abi.FuncPCABI0(usleep_trampoline)), unsafe.Pointer(&usec)) 141} 142func usleep_trampoline() 143 144//go:nosplit 145//go:cgo_unsafe_args 146func usleep_no_g(usec uint32) { 147 asmcgocall_no_g(unsafe.Pointer(abi.FuncPCABI0(usleep_trampoline)), unsafe.Pointer(&usec)) 148} 149 150//go:nosplit 151//go:cgo_unsafe_args 152func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 { 153 ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) 154 KeepAlive(mib) 155 KeepAlive(out) 156 KeepAlive(size) 157 KeepAlive(dst) 158 return ret 159} 160func sysctl_trampoline() 161 162//go:nosplit 163//go:cgo_unsafe_args 164func fcntl(fd, cmd, arg int32) (ret int32, errno int32) { 165 args := struct { 166 fd, cmd, arg int32 167 ret, errno int32 168 }{fd, cmd, arg, 0, 0} 169 libcCall(unsafe.Pointer(abi.FuncPCABI0(fcntl_trampoline)), unsafe.Pointer(&args)) 170 return args.ret, args.errno 171} 172func fcntl_trampoline() 173 174//go:nosplit 175func nanotime1() int64 { 176 var ts timespec 177 args := struct { 178 clock_id int32 179 tp unsafe.Pointer 180 }{_CLOCK_MONOTONIC, unsafe.Pointer(&ts)} 181 if errno := libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)); errno < 0 { 182 // Avoid growing the nosplit stack. 183 systemstack(func() { 184 println("runtime: errno", -errno) 185 throw("clock_gettime failed") 186 }) 187 } 188 return ts.tv_sec*1e9 + int64(ts.tv_nsec) 189} 190func clock_gettime_trampoline() 191 192//go:nosplit 193func walltime() (int64, int32) { 194 var ts timespec 195 args := struct { 196 clock_id int32 197 tp unsafe.Pointer 198 }{_CLOCK_REALTIME, unsafe.Pointer(&ts)} 199 if errno := libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)); errno < 0 { 200 // Avoid growing the nosplit stack. 201 systemstack(func() { 202 println("runtime: errno", -errno) 203 throw("clock_gettime failed") 204 }) 205 } 206 return ts.tv_sec, int32(ts.tv_nsec) 207} 208 209//go:nosplit 210//go:cgo_unsafe_args 211func kqueue() int32 { 212 return libcCall(unsafe.Pointer(abi.FuncPCABI0(kqueue_trampoline)), nil) 213} 214func kqueue_trampoline() 215 216//go:nosplit 217//go:cgo_unsafe_args 218func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { 219 ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(kevent_trampoline)), unsafe.Pointer(&kq)) 220 KeepAlive(ch) 221 KeepAlive(ev) 222 KeepAlive(ts) 223 return ret 224} 225func kevent_trampoline() 226 227//go:nosplit 228//go:cgo_unsafe_args 229func sigaction(sig uint32, new *sigactiont, old *sigactiont) { 230 libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaction_trampoline)), unsafe.Pointer(&sig)) 231 KeepAlive(new) 232 KeepAlive(old) 233} 234func sigaction_trampoline() 235 236//go:nosplit 237//go:cgo_unsafe_args 238func sigprocmask(how uint32, new *sigset, old *sigset) { 239 // sigprocmask is called from sigsave, which is called from needm. 240 // As such, we have to be able to run with no g here. 241 asmcgocall_no_g(unsafe.Pointer(abi.FuncPCABI0(sigprocmask_trampoline)), unsafe.Pointer(&how)) 242 KeepAlive(new) 243 KeepAlive(old) 244} 245func sigprocmask_trampoline() 246 247//go:nosplit 248//go:cgo_unsafe_args 249func sigaltstack(new *stackt, old *stackt) { 250 libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaltstack_trampoline)), unsafe.Pointer(&new)) 251 KeepAlive(new) 252 KeepAlive(old) 253} 254func sigaltstack_trampoline() 255 256// Not used on OpenBSD, but must be defined. 257func exitThread(wait *atomic.Uint32) { 258 throw("exitThread") 259} 260 261//go:nosplit 262//go:cgo_unsafe_args 263func issetugid() (ret int32) { 264 libcCall(unsafe.Pointer(abi.FuncPCABI0(issetugid_trampoline)), unsafe.Pointer(&ret)) 265 return 266} 267func issetugid_trampoline() 268 269// Tell the linker that the libc_* functions are to be found 270// in a system library, with the libc_ prefix missing. 271 272//go:cgo_import_dynamic libc_errno __errno "libc.so" 273//go:cgo_import_dynamic libc_exit exit "libc.so" 274//go:cgo_import_dynamic libc_getthrid getthrid "libc.so" 275//go:cgo_import_dynamic libc_sched_yield sched_yield "libc.so" 276//go:cgo_import_dynamic libc_thrkill thrkill "libc.so" 277 278//go:cgo_import_dynamic libc_mmap mmap "libc.so" 279//go:cgo_import_dynamic libc_munmap munmap "libc.so" 280//go:cgo_import_dynamic libc_madvise madvise "libc.so" 281 282//go:cgo_import_dynamic libc_open open "libc.so" 283//go:cgo_import_dynamic libc_close close "libc.so" 284//go:cgo_import_dynamic libc_read read "libc.so" 285//go:cgo_import_dynamic libc_write write "libc.so" 286//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" 287 288//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" 289//go:cgo_import_dynamic libc_setitimer setitimer "libc.so" 290//go:cgo_import_dynamic libc_usleep usleep "libc.so" 291//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" 292//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" 293//go:cgo_import_dynamic libc_getpid getpid "libc.so" 294//go:cgo_import_dynamic libc_kill kill "libc.so" 295//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" 296//go:cgo_import_dynamic libc_kevent kevent "libc.so" 297 298//go:cgo_import_dynamic libc_sigaction sigaction "libc.so" 299//go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.so" 300 301//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" 302 303//go:cgo_import_dynamic _ _ "libc.so" 304