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_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 alligned 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 MOVQ g_m(BX), BX 84 MOVQ m_perrno(BX), DX 85 CMPQ DX, $0 86 JEQ skiperrno1 87 MOVL $0, 0(DX) 88 89 skiperrno1: 90 CMPQ R11, $0 91 JEQ skipargs 92 // Load 6 args into correspondent registers. 93 MOVQ 0(R11), DI 94 MOVQ 8(R11), SI 95 MOVQ 16(R11), DX 96 MOVQ 24(R11), CX 97 MOVQ 32(R11), R8 98 MOVQ 40(R11), R9 99 skipargs: 100 101 // Call SysV function 102 CALL AX 103 104 // Return result 105 POPQ DI 106 MOVQ AX, libcall_r1(DI) 107 MOVQ DX, libcall_r2(DI) 108 109 get_tls(CX) 110 MOVQ g(CX), BX 111 MOVQ g_m(BX), BX 112 MOVQ m_perrno(BX), AX 113 CMPQ AX, $0 114 JEQ skiperrno2 115 MOVL 0(AX), AX 116 MOVQ AX, libcall_err(DI) 117 118 skiperrno2: 119 RET 120 121 // uint32 tstart_sysvicall(M *newm); 122 TEXT runtimetstart_sysvicall(SB),NOSPLIT,$0 123 // DI contains first arg newm 124 MOVQ m_g0(DI), DX // g 125 126 // Make TLS entries point at g and m. 127 get_tls(BX) 128 MOVQ DX, g(BX) 129 MOVQ DI, g_m(DX) 130 131 // Layout new m scheduler stack on os stack. 132 MOVQ SP, AX 133 MOVQ AX, (g_stack+stack_hi)(DX) 134 SUBQ $(0x100000), AX // stack size 135 MOVQ AX, (g_stack+stack_lo)(DX) 136 ADDQ $const__StackGuard, AX 137 MOVQ AX, g_stackguard0(DX) 138 MOVQ AX, g_stackguard1(DX) 139 140 // Someday the convention will be D is always cleared. 141 CLD 142 143 CALL runtimestackcheck(SB) // clobbers AX,CX 144 CALL runtimemstart(SB) 145 146 XORL AX, AX // return 0 == success 147 MOVL AX, ret+8(FP) 148 RET 149 150 // Careful, this is called by __sighndlr, a libc function. We must preserve 151 // registers as per AMD 64 ABI. 152 TEXT runtimesigtramp(SB),NOSPLIT,$0 153 // Note that we are executing on altsigstack here, so we have 154 // more stack available than NOSPLIT would have us believe. 155 // To defeat the linker, we make our own stack frame with 156 // more space: 157 SUBQ $184, SP 158 159 // save registers 160 MOVQ BX, 32(SP) 161 MOVQ BP, 40(SP) 162 MOVQ R12, 48(SP) 163 MOVQ R13, 56(SP) 164 MOVQ R14, 64(SP) 165 MOVQ R15, 72(SP) 166 167 get_tls(BX) 168 // check that g exists 169 MOVQ g(BX), R10 170 CMPQ R10, $0 171 JNE allgood 172 MOVQ DI, 0(SP) 173 MOVQ $runtimebadsignal(SB), AX 174 CALL AX 175 JMP exit 176 177 allgood: 178 // save g 179 MOVQ R10, 80(SP) 180 181 // Save m->libcall and m->scratch. We need to do this because we 182 // might get interrupted by a signal in runtimeasmcgocall. 183 184 // save m->libcall 185 MOVQ g_m(R10), BP 186 LEAQ m_libcall(BP), R11 187 MOVQ libcall_fn(R11), R10 188 MOVQ R10, 88(SP) 189 MOVQ libcall_args(R11), R10 190 MOVQ R10, 96(SP) 191 MOVQ libcall_n(R11), R10 192 MOVQ R10, 104(SP) 193 MOVQ libcall_r1(R11), R10 194 MOVQ R10, 168(SP) 195 MOVQ libcall_r2(R11), R10 196 MOVQ R10, 176(SP) 197 198 // save m->scratch 199 LEAQ m_scratch(BP), R11 200 MOVQ 0(R11), R10 201 MOVQ R10, 112(SP) 202 MOVQ 8(R11), R10 203 MOVQ R10, 120(SP) 204 MOVQ 16(R11), R10 205 MOVQ R10, 128(SP) 206 MOVQ 24(R11), R10 207 MOVQ R10, 136(SP) 208 MOVQ 32(R11), R10 209 MOVQ R10, 144(SP) 210 MOVQ 40(R11), R10 211 MOVQ R10, 152(SP) 212 213 // save errno, it might be EINTR; stuff we do here might reset it. 214 MOVQ m_perrno(BP), R10 215 MOVL 0(R10), R10 216 MOVQ R10, 160(SP) 217 218 MOVQ g(BX), R10 219 // g = m->gsignal 220 MOVQ m_gsignal(BP), BP 221 MOVQ BP, g(BX) 222 223 // prepare call 224 MOVQ DI, 0(SP) 225 MOVQ SI, 8(SP) 226 MOVQ DX, 16(SP) 227 MOVQ R10, 24(SP) 228 CALL runtimesighandler(SB) 229 230 get_tls(BX) 231 MOVQ g(BX), BP 232 MOVQ g_m(BP), BP 233 // restore libcall 234 LEAQ m_libcall(BP), R11 235 MOVQ 88(SP), R10 236 MOVQ R10, libcall_fn(R11) 237 MOVQ 96(SP), R10 238 MOVQ R10, libcall_args(R11) 239 MOVQ 104(SP), R10 240 MOVQ R10, libcall_n(R11) 241 MOVQ 168(SP), R10 242 MOVQ R10, libcall_r1(R11) 243 MOVQ 176(SP), R10 244 MOVQ R10, libcall_r2(R11) 245 246 // restore scratch 247 LEAQ m_scratch(BP), R11 248 MOVQ 112(SP), R10 249 MOVQ R10, 0(R11) 250 MOVQ 120(SP), R10 251 MOVQ R10, 8(R11) 252 MOVQ 128(SP), R10 253 MOVQ R10, 16(R11) 254 MOVQ 136(SP), R10 255 MOVQ R10, 24(R11) 256 MOVQ 144(SP), R10 257 MOVQ R10, 32(R11) 258 MOVQ 152(SP), R10 259 MOVQ R10, 40(R11) 260 261 // restore errno 262 MOVQ m_perrno(BP), R11 263 MOVQ 160(SP), R10 264 MOVL R10, 0(R11) 265 266 // restore g 267 MOVQ 80(SP), R10 268 MOVQ R10, g(BX) 269 270 exit: 271 // restore registers 272 MOVQ 32(SP), BX 273 MOVQ 40(SP), BP 274 MOVQ 48(SP), R12 275 MOVQ 56(SP), R13 276 MOVQ 64(SP), R14 277 MOVQ 72(SP), R15 278 279 ADDQ $184, SP 280 RET 281 282 // Called from runtimeusleep (Go). Can be called on Go stack, on OS stack, 283 // can also be called in cgo callback path without a g->m. 284 TEXT runtimeusleep1(SB),NOSPLIT,$0 285 MOVL usec+0(FP), DI 286 MOVQ $runtimeusleep2(SB), AX // to hide from 6l 287 288 // Execute call on m->g0. 289 get_tls(R15) 290 CMPQ R15, $0 291 JE noswitch 292 293 MOVQ g(R15), R13 294 CMPQ R13, $0 295 JE noswitch 296 MOVQ g_m(R13), R13 297 CMPQ R13, $0 298 JE noswitch 299 // TODO(aram): do something about the cpu profiler here. 300 301 MOVQ m_g0(R13), R14 302 CMPQ g(R15), R14 303 JNE switch 304 // executing on m->g0 already 305 CALL AX 306 RET 307 308 switch: 309 // Switch to m->g0 stack and back. 310 MOVQ (g_sched+gobuf_sp)(R14), R14 311 MOVQ SP, -8(R14) 312 LEAQ -8(R14), SP 313 CALL AX 314 MOVQ 0(SP), SP 315 RET 316 317 noswitch: 318 // Not a Go-managed thread. Do not switch stack. 319 CALL AX 320 RET 321 322 // Runs on OS stack. duration (in s units) is in DI. 323 TEXT runtimeusleep2(SB),NOSPLIT,$0 324 LEAQ libc_usleep(SB), AX 325 CALL AX 326 RET 327 328 // Runs on OS stack, called from runtimeosyield. 329 TEXT runtimeosyield1(SB),NOSPLIT,$0 330 LEAQ libc_sched_yield(SB), AX 331 CALL AX 332 RET 333 334 // func now() (sec int64, nsec int32) 335 TEXT timenow(SB),NOSPLIT,$8-12 336 CALL runtimenanotime(SB) 337 MOVQ 0(SP), AX 338 339 // generated code for 340 // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } 341 // adapted to reduce duplication 342 MOVQ AX, CX 343 MOVQ $1360296554856532783, AX 344 MULQ CX 345 ADDQ CX, DX 346 RCRQ $1, DX 347 SHRQ $29, DX 348 MOVQ DX, sec+0(FP) 349 IMULQ $1000000000, DX 350 SUBQ DX, CX 351 MOVL CX, nsec+8(FP) 352 RET 353