1 // Copyright 2014 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 // System calls and other sys.stuff for AMD64, SunOS 6 // /usr/include/sys/syscall.h for syscall numbers. 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // This is needed by asm_amd64.s 14 TEXT runtimesettls(SB),NOSPLIT,$8 15 RET 16 17 // void libc_miniterrno(void *(*___errno)(void)); 18 // 19 // Set the TLS errno pointer in M. 20 // 21 // Called using runtimeasmcgocall from os_solaris.c:/minit. 22 // NOT USING GO CALLING CONVENTION. 23 TEXT runtimeminiterrno(SB),NOSPLIT,$0 24 // asmcgocall will put first argument into DI. 25 CALL DI // SysV ABI so returns in AX 26 get_tls(CX) 27 MOVQ g(CX), BX 28 MOVQ g_m(BX), BX 29 MOVQ AX, (m_mOS+mOS_perrno)(BX) 30 RET 31 32 // int64 runtimenanotime1(void); 33 // 34 // clock_gettime(3c) wrapper because Timespec is too large for 35 // runtimenanotime stack. 36 // 37 // Called using runtimesysvicall6 from os_solaris.c:/nanotime. 38 // NOT USING GO CALLING CONVENTION. 39 TEXT runtimenanotime1(SB),NOSPLIT,$0 40 // need space for the timespec argument. 41 SUBQ $64, SP // 16 bytes will do, but who knows in the future? 42 MOVQ $3, DI // CLOCK_REALTIME from <sys/time_impl.h> 43 MOVQ SP, SI 44 LEAQ libc_clock_gettime(SB), AX 45 CALL AX 46 MOVQ (SP), AX // tv_sec from struct timespec 47 IMULQ $1000000000, AX // multiply into nanoseconds 48 ADDQ 8(SP), AX // tv_nsec, offset should be stable. 49 ADDQ $64, SP 50 RET 51 52 // pipe(3c) wrapper that returns fds in AX, DX. 53 // NOT USING GO CALLING CONVENTION. 54 TEXT runtimepipe1(SB),NOSPLIT,$0 55 SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte aligned 56 MOVQ SP, DI 57 LEAQ libc_pipe(SB), AX 58 CALL AX 59 MOVL 0(SP), AX 60 MOVL 4(SP), DX 61 ADDQ $16, SP 62 RET 63 64 // Call a library function with SysV calling conventions. 65 // The called function can take a maximum of 6 INTEGER class arguments, 66 // see 67 // Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell 68 // System V Application Binary Interface 69 // AMD64 Architecture Processor Supplement 70 // section 3.2.3. 71 // 72 // Called by runtimeasmcgocall or runtimecgocall. 73 // NOT USING GO CALLING CONVENTION. 74 TEXT runtimeasmsysvicall6(SB),NOSPLIT,$0 75 // asmcgocall will put first argument into DI. 76 PUSHQ DI // save for later 77 MOVQ libcall_fn(DI), AX 78 MOVQ libcall_args(DI), R11 79 MOVQ libcall_n(DI), R10 80 81 get_tls(CX) 82 MOVQ g(CX), BX 83 CMPQ BX, $0 84 JEQ skiperrno1 85 MOVQ g_m(BX), BX 86 MOVQ (m_mOS+mOS_perrno)(BX), DX 87 CMPQ DX, $0 88 JEQ skiperrno1 89 MOVL $0, 0(DX) 90 91 skiperrno1: 92 CMPQ R11, $0 93 JEQ skipargs 94 // Load 6 args into correspondent registers. 95 MOVQ 0(R11), DI 96 MOVQ 8(R11), SI 97 MOVQ 16(R11), DX 98 MOVQ 24(R11), CX 99 MOVQ 32(R11), R8 100 MOVQ 40(R11), R9 101 skipargs: 102 103 // Call SysV function 104 CALL AX 105 106 // Return result 107 POPQ DI 108 MOVQ AX, libcall_r1(DI) 109 MOVQ DX, libcall_r2(DI) 110 111 get_tls(CX) 112 MOVQ g(CX), BX 113 CMPQ BX, $0 114 JEQ skiperrno2 115 MOVQ g_m(BX), BX 116 MOVQ (m_mOS+mOS_perrno)(BX), AX 117 CMPQ AX, $0 118 JEQ skiperrno2 119 MOVL 0(AX), AX 120 MOVQ AX, libcall_err(DI) 121 122 skiperrno2: 123 RET 124 125 // uint32 tstart_sysvicall(M *newm); 126 TEXT runtimetstart_sysvicall(SB),NOSPLIT,$0 127 // DI contains first arg newm 128 MOVQ m_g0(DI), DX // g 129 130 // Make TLS entries point at g and m. 131 get_tls(BX) 132 MOVQ DX, g(BX) 133 MOVQ DI, g_m(DX) 134 135 // Layout new m scheduler stack on os stack. 136 MOVQ SP, AX 137 MOVQ AX, (g_stack+stack_hi)(DX) 138 SUBQ $(0x100000), AX // stack size 139 MOVQ AX, (g_stack+stack_lo)(DX) 140 ADDQ $const__StackGuard, AX 141 MOVQ AX, g_stackguard0(DX) 142 MOVQ AX, g_stackguard1(DX) 143 144 // Someday the convention will be D is always cleared. 145 CLD 146 147 CALL runtimestackcheck(SB) // clobbers AX,CX 148 CALL runtimemstart(SB) 149 150 XORL AX, AX // return 0 == success 151 MOVL AX, ret+8(FP) 152 RET 153 154 // Careful, this is called by __sighndlr, a libc function. We must preserve 155 // registers as per AMD 64 ABI. 156 TEXT runtimesigtramp(SB),NOSPLIT,$0 157 // Note that we are executing on altsigstack here, so we have 158 // more stack available than NOSPLIT would have us believe. 159 // To defeat the linker, we make our own stack frame with 160 // more space: 161 SUBQ $184, SP 162 163 // save registers 164 MOVQ BX, 32(SP) 165 MOVQ BP, 40(SP) 166 MOVQ R12, 48(SP) 167 MOVQ R13, 56(SP) 168 MOVQ R14, 64(SP) 169 MOVQ R15, 72(SP) 170 171 get_tls(BX) 172 // check that g exists 173 MOVQ g(BX), R10 174 CMPQ R10, $0 175 JNE allgood 176 MOVQ SI, 80(SP) 177 MOVQ DX, 88(SP) 178 LEAQ 80(SP), AX 179 MOVQ DI, 0(SP) 180 MOVQ AX, 8(SP) 181 MOVQ $runtimebadsignal(SB), AX 182 CALL AX 183 JMP exit 184 185 allgood: 186 // save g 187 MOVQ R10, 80(SP) 188 189 // Save m->libcall and m->scratch. We need to do this because we 190 // might get interrupted by a signal in runtimeasmcgocall. 191 192 // save m->libcall 193 MOVQ g_m(R10), BP 194 LEAQ m_libcall(BP), R11 195 MOVQ libcall_fn(R11), R10 196 MOVQ R10, 88(SP) 197 MOVQ libcall_args(R11), R10 198 MOVQ R10, 96(SP) 199 MOVQ libcall_n(R11), R10 200 MOVQ R10, 104(SP) 201 MOVQ libcall_r1(R11), R10 202 MOVQ R10, 168(SP) 203 MOVQ libcall_r2(R11), R10 204 MOVQ R10, 176(SP) 205 206 // save m->scratch 207 LEAQ (m_mOS+mOS_scratch)(BP), R11 208 MOVQ 0(R11), R10 209 MOVQ R10, 112(SP) 210 MOVQ 8(R11), R10 211 MOVQ R10, 120(SP) 212 MOVQ 16(R11), R10 213 MOVQ R10, 128(SP) 214 MOVQ 24(R11), R10 215 MOVQ R10, 136(SP) 216 MOVQ 32(R11), R10 217 MOVQ R10, 144(SP) 218 MOVQ 40(R11), R10 219 MOVQ R10, 152(SP) 220 221 // save errno, it might be EINTR; stuff we do here might reset it. 222 MOVQ (m_mOS+mOS_perrno)(BP), R10 223 MOVL 0(R10), R10 224 MOVQ R10, 160(SP) 225 226 MOVQ g(BX), R10 227 // g = m->gsignal 228 MOVQ m_gsignal(BP), BP 229 MOVQ BP, g(BX) 230 231 // TODO: If current SP is not in gsignal.stack, then adjust. 232 233 // prepare call 234 MOVQ DI, 0(SP) 235 MOVQ SI, 8(SP) 236 MOVQ DX, 16(SP) 237 MOVQ R10, 24(SP) 238 CALL runtimesighandler(SB) 239 240 get_tls(BX) 241 MOVQ g(BX), BP 242 MOVQ g_m(BP), BP 243 // restore libcall 244 LEAQ m_libcall(BP), R11 245 MOVQ 88(SP), R10 246 MOVQ R10, libcall_fn(R11) 247 MOVQ 96(SP), R10 248 MOVQ R10, libcall_args(R11) 249 MOVQ 104(SP), R10 250 MOVQ R10, libcall_n(R11) 251 MOVQ 168(SP), R10 252 MOVQ R10, libcall_r1(R11) 253 MOVQ 176(SP), R10 254 MOVQ R10, libcall_r2(R11) 255 256 // restore scratch 257 LEAQ (m_mOS+mOS_scratch)(BP), R11 258 MOVQ 112(SP), R10 259 MOVQ R10, 0(R11) 260 MOVQ 120(SP), R10 261 MOVQ R10, 8(R11) 262 MOVQ 128(SP), R10 263 MOVQ R10, 16(R11) 264 MOVQ 136(SP), R10 265 MOVQ R10, 24(R11) 266 MOVQ 144(SP), R10 267 MOVQ R10, 32(R11) 268 MOVQ 152(SP), R10 269 MOVQ R10, 40(R11) 270 271 // restore errno 272 MOVQ (m_mOS+mOS_perrno)(BP), R11 273 MOVQ 160(SP), R10 274 MOVL R10, 0(R11) 275 276 // restore g 277 MOVQ 80(SP), R10 278 MOVQ R10, g(BX) 279 280 exit: 281 // restore registers 282 MOVQ 32(SP), BX 283 MOVQ 40(SP), BP 284 MOVQ 48(SP), R12 285 MOVQ 56(SP), R13 286 MOVQ 64(SP), R14 287 MOVQ 72(SP), R15 288 289 ADDQ $184, SP 290 RET 291 292 TEXT runtimesigfwd(SB),NOSPLIT,$0-32 293 MOVQ fn+0(FP), AX 294 MOVL sig+8(FP), DI 295 MOVQ info+16(FP), SI 296 MOVQ ctx+24(FP), DX 297 PUSHQ BP 298 MOVQ SP, BP 299 ANDQ $~15, SP // alignment for x86_64 ABI 300 CALL AX 301 MOVQ BP, SP 302 POPQ BP 303 RET 304 305 // Called from runtimeusleep (Go). Can be called on Go stack, on OS stack, 306 // can also be called in cgo callback path without a g->m. 307 TEXT runtimeusleep1(SB),NOSPLIT,$0 308 MOVL usec+0(FP), DI 309 MOVQ $runtimeusleep2(SB), AX // to hide from 6l 310 311 // Execute call on m->g0. 312 get_tls(R15) 313 CMPQ R15, $0 314 JE noswitch 315 316 MOVQ g(R15), R13 317 CMPQ R13, $0 318 JE noswitch 319 MOVQ g_m(R13), R13 320 CMPQ R13, $0 321 JE noswitch 322 // TODO(aram): do something about the cpu profiler here. 323 324 MOVQ m_g0(R13), R14 325 CMPQ g(R15), R14 326 JNE switch 327 // executing on m->g0 already 328 CALL AX 329 RET 330 331 switch: 332 // Switch to m->g0 stack and back. 333 MOVQ (g_sched+gobuf_sp)(R14), R14 334 MOVQ SP, -8(R14) 335 LEAQ -8(R14), SP 336 CALL AX 337 MOVQ 0(SP), SP 338 RET 339 340 noswitch: 341 // Not a Go-managed thread. Do not switch stack. 342 CALL AX 343 RET 344 345 // Runs on OS stack. duration (in s units) is in DI. 346 TEXT runtimeusleep2(SB),NOSPLIT,$0 347 LEAQ libc_usleep(SB), AX 348 CALL AX 349 RET 350 351 // Runs on OS stack, called from runtimeosyield. 352 TEXT runtimeosyield1(SB),NOSPLIT,$0 353 LEAQ libc_sched_yield(SB), AX 354 CALL AX 355 RET 356 357 // func now() (sec int64, nsec int32) 358 TEXT timenow(SB),NOSPLIT,$8-12 359 CALL runtimenanotime(SB) 360 MOVQ 0(SP), AX 361 362 // generated code for 363 // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } 364 // adapted to reduce duplication 365 MOVQ AX, CX 366 MOVQ $1360296554856532783, AX 367 MULQ CX 368 ADDQ CX, DX 369 RCRQ $1, DX 370 SHRQ $29, DX 371 MOVQ DX, sec+0(FP) 372 IMULQ $1000000000, DX 373 SUBQ DX, CX 374 MOVL CX, nsec+8(FP) 375 RET 376