1 // Copyright 2009 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 386, FreeBSD 6 // /usr/src/sys/kern/syscalls.master for syscall numbers. 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 TEXT runtimesys_umtx_op(SB),NOSPLIT,$-4 14 MOVL $454, AX 15 INT $0x80 16 MOVL AX, ret+20(FP) 17 RET 18 19 TEXT runtimethr_new(SB),NOSPLIT,$-4 20 MOVL $455, AX 21 INT $0x80 22 RET 23 24 TEXT runtimethr_start(SB),NOSPLIT,$0 25 MOVL mm+0(FP), AX 26 MOVL m_g0(AX), BX 27 LEAL m_tls(AX), BP 28 MOVL m_id(AX), DI 29 ADDL $7, DI 30 PUSHAL 31 PUSHL $32 32 PUSHL BP 33 PUSHL DI 34 CALL runtimesetldt(SB) 35 POPL AX 36 POPL AX 37 POPL AX 38 POPAL 39 get_tls(CX) 40 MOVL BX, g(CX) 41 42 MOVL AX, g_m(BX) 43 CALL runtimestackcheck(SB) // smashes AX 44 CALL runtimemstart(SB) 45 46 MOVL 0, AX // crash (not reached) 47 48 // Exit the entire program (like C exit) 49 TEXT runtimeexit(SB),NOSPLIT,$-4 50 MOVL $1, AX 51 INT $0x80 52 MOVL $0xf1, 0xf1 // crash 53 RET 54 55 GLOBL exitStack<>(SB),RODATA,$8 56 DATA exitStack<>+0x00(SB)/4, $0 57 DATA exitStack<>+0x04(SB)/4, $0 58 59 // func exitThread(wait *uint32) 60 TEXT runtimeexitThread(SB),NOSPLIT,$0-4 61 MOVL wait+0(FP), AX 62 // We're done using the stack. 63 MOVL $0, (AX) 64 // thr_exit takes a single pointer argument, which it expects 65 // on the stack. We want to pass 0, so switch over to a fake 66 // stack of 0s. It won't write to the stack. 67 MOVL $exitStack<>(SB), SP 68 MOVL $431, AX // thr_exit 69 INT $0x80 70 MOVL $0xf1, 0xf1 // crash 71 JMP 0(PC) 72 73 TEXT runtimeopen(SB),NOSPLIT,$-4 74 MOVL $5, AX 75 INT $0x80 76 JAE 2(PC) 77 MOVL $-1, AX 78 MOVL AX, ret+12(FP) 79 RET 80 81 TEXT runtimeclosefd(SB),NOSPLIT,$-4 82 MOVL $6, AX 83 INT $0x80 84 JAE 2(PC) 85 MOVL $-1, AX 86 MOVL AX, ret+4(FP) 87 RET 88 89 TEXT runtimeread(SB),NOSPLIT,$-4 90 MOVL $3, AX 91 INT $0x80 92 JAE 2(PC) 93 MOVL $-1, AX 94 MOVL AX, ret+12(FP) 95 RET 96 97 TEXT runtimewrite(SB),NOSPLIT,$-4 98 MOVL $4, AX 99 INT $0x80 100 JAE 2(PC) 101 MOVL $-1, AX 102 MOVL AX, ret+12(FP) 103 RET 104 105 TEXT runtimegetrlimit(SB),NOSPLIT,$-4 106 MOVL $194, AX 107 INT $0x80 108 MOVL AX, ret+8(FP) 109 RET 110 111 TEXT runtimeraise(SB),NOSPLIT,$16 112 // thr_self(&8(SP)) 113 LEAL 8(SP), AX 114 MOVL AX, 4(SP) 115 MOVL $432, AX 116 INT $0x80 117 // thr_kill(self, SIGPIPE) 118 MOVL 8(SP), AX 119 MOVL AX, 4(SP) 120 MOVL sig+0(FP), AX 121 MOVL AX, 8(SP) 122 MOVL $433, AX 123 INT $0x80 124 RET 125 126 TEXT runtimeraiseproc(SB),NOSPLIT,$16 127 // getpid 128 MOVL $20, AX 129 INT $0x80 130 // kill(self, sig) 131 MOVL AX, 4(SP) 132 MOVL sig+0(FP), AX 133 MOVL AX, 8(SP) 134 MOVL $37, AX 135 INT $0x80 136 RET 137 138 TEXT runtimemmap(SB),NOSPLIT,$32 139 LEAL addr+0(FP), SI 140 LEAL 4(SP), DI 141 CLD 142 MOVSL 143 MOVSL 144 MOVSL 145 MOVSL 146 MOVSL 147 MOVSL 148 MOVL $0, AX // top 32 bits of file offset 149 STOSL 150 MOVL $477, AX 151 INT $0x80 152 JAE ok 153 MOVL $0, p+24(FP) 154 MOVL AX, err+28(FP) 155 RET 156 ok: 157 MOVL AX, p+24(FP) 158 MOVL $0, err+28(FP) 159 RET 160 161 TEXT runtimemunmap(SB),NOSPLIT,$-4 162 MOVL $73, AX 163 INT $0x80 164 JAE 2(PC) 165 MOVL $0xf1, 0xf1 // crash 166 RET 167 168 TEXT runtimemadvise(SB),NOSPLIT,$-4 169 MOVL $75, AX // madvise 170 INT $0x80 171 // ignore failure - maybe pages are locked 172 RET 173 174 TEXT runtimesetitimer(SB), NOSPLIT, $-4 175 MOVL $83, AX 176 INT $0x80 177 RET 178 179 // func walltime() (sec int64, nsec int32) 180 TEXT runtimewalltime(SB), NOSPLIT, $32 181 MOVL $232, AX // clock_gettime 182 LEAL 12(SP), BX 183 MOVL $0, 4(SP) // CLOCK_REALTIME 184 MOVL BX, 8(SP) 185 INT $0x80 186 MOVL 12(SP), AX // sec 187 MOVL 16(SP), BX // nsec 188 189 // sec is in AX, nsec in BX 190 MOVL AX, sec_lo+0(FP) 191 MOVL $0, sec_hi+4(FP) 192 MOVL BX, nsec+8(FP) 193 RET 194 195 // int64 nanotime(void) so really 196 // void nanotime(int64 *nsec) 197 TEXT runtimenanotime(SB), NOSPLIT, $32 198 MOVL $232, AX 199 LEAL 12(SP), BX 200 // We can use CLOCK_MONOTONIC_FAST here when we drop 201 // support for FreeBSD 8-STABLE. 202 MOVL $4, 4(SP) // CLOCK_MONOTONIC 203 MOVL BX, 8(SP) 204 INT $0x80 205 MOVL 12(SP), AX // sec 206 MOVL 16(SP), BX // nsec 207 208 // sec is in AX, nsec in BX 209 // convert to DX:AX nsec 210 MOVL $1000000000, CX 211 MULL CX 212 ADDL BX, AX 213 ADCL $0, DX 214 215 MOVL AX, ret_lo+0(FP) 216 MOVL DX, ret_hi+4(FP) 217 RET 218 219 220 TEXT runtimesigaction(SB),NOSPLIT,$-4 221 MOVL $416, AX 222 INT $0x80 223 JAE 2(PC) 224 MOVL $0xf1, 0xf1 // crash 225 RET 226 227 TEXT runtimesigfwd(SB),NOSPLIT,$12-16 228 MOVL fn+0(FP), AX 229 MOVL sig+4(FP), BX 230 MOVL info+8(FP), CX 231 MOVL ctx+12(FP), DX 232 MOVL SP, SI 233 SUBL $32, SP 234 ANDL $~15, SP // align stack: handler might be a C function 235 MOVL BX, 0(SP) 236 MOVL CX, 4(SP) 237 MOVL DX, 8(SP) 238 MOVL SI, 12(SP) // save SI: handler might be a Go function 239 CALL AX 240 MOVL 12(SP), AX 241 MOVL AX, SP 242 RET 243 244 TEXT runtimesigtramp(SB),NOSPLIT,$12 245 MOVL signo+0(FP), BX 246 MOVL BX, 0(SP) 247 MOVL info+4(FP), BX 248 MOVL BX, 4(SP) 249 MOVL context+8(FP), BX 250 MOVL BX, 8(SP) 251 CALL runtimesigtrampgo(SB) 252 253 // call sigreturn 254 MOVL context+8(FP), AX 255 MOVL $0, 0(SP) // syscall gap 256 MOVL AX, 4(SP) 257 MOVL $417, AX // sigreturn(ucontext) 258 INT $0x80 259 MOVL $0xf1, 0xf1 // crash 260 RET 261 262 TEXT runtimesigaltstack(SB),NOSPLIT,$0 263 MOVL $53, AX 264 INT $0x80 265 JAE 2(PC) 266 MOVL $0xf1, 0xf1 // crash 267 RET 268 269 TEXT runtimeusleep(SB),NOSPLIT,$20 270 MOVL $0, DX 271 MOVL usec+0(FP), AX 272 MOVL $1000000, CX 273 DIVL CX 274 MOVL AX, 12(SP) // tv_sec 275 MOVL $1000, AX 276 MULL DX 277 MOVL AX, 16(SP) // tv_nsec 278 279 MOVL $0, 0(SP) 280 LEAL 12(SP), AX 281 MOVL AX, 4(SP) // arg 1 - rqtp 282 MOVL $0, 8(SP) // arg 2 - rmtp 283 MOVL $240, AX // sys_nanosleep 284 INT $0x80 285 RET 286 287 /* 288 descriptor entry format for system call 289 is the native machine format, ugly as it is: 290 291 2-byte limit 292 3-byte base 293 1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type 294 1-byte: 0x80=limit is *4k, 0x40=32-bit operand size, 295 0x0F=4 more bits of limit 296 1 byte: 8 more bits of base 297 298 int i386_get_ldt(int, union ldt_entry *, int); 299 int i386_set_ldt(int, const union ldt_entry *, int); 300 301 */ 302 303 // setldt(int entry, int address, int limit) 304 TEXT runtimesetldt(SB),NOSPLIT,$32 305 MOVL address+4(FP), BX // aka base 306 // see comment in sys_linux_386.s; freebsd is similar 307 ADDL $0x4, BX 308 309 // set up data_desc 310 LEAL 16(SP), AX // struct data_desc 311 MOVL $0, 0(AX) 312 MOVL $0, 4(AX) 313 314 MOVW BX, 2(AX) 315 SHRL $16, BX 316 MOVB BX, 4(AX) 317 SHRL $8, BX 318 MOVB BX, 7(AX) 319 320 MOVW $0xffff, 0(AX) 321 MOVB $0xCF, 6(AX) // 32-bit operand, 4k limit unit, 4 more bits of limit 322 323 MOVB $0xF2, 5(AX) // r/w data descriptor, dpl=3, present 324 325 // call i386_set_ldt(entry, desc, 1) 326 MOVL $0xffffffff, 0(SP) // auto-allocate entry and return in AX 327 MOVL AX, 4(SP) 328 MOVL $1, 8(SP) 329 CALL runtimei386_set_ldt(SB) 330 331 // compute segment selector - (entry*8+7) 332 SHLL $3, AX 333 ADDL $7, AX 334 MOVW AX, GS 335 RET 336 337 TEXT runtimei386_set_ldt(SB),NOSPLIT,$16 338 LEAL args+0(FP), AX // 0(FP) == 4(SP) before SP got moved 339 MOVL $0, 0(SP) // syscall gap 340 MOVL $1, 4(SP) 341 MOVL AX, 8(SP) 342 MOVL $165, AX 343 INT $0x80 344 JAE 2(PC) 345 INT $3 346 RET 347 348 TEXT runtimesysctl(SB),NOSPLIT,$28 349 LEAL mib+0(FP), SI 350 LEAL 4(SP), DI 351 CLD 352 MOVSL // arg 1 - name 353 MOVSL // arg 2 - namelen 354 MOVSL // arg 3 - oldp 355 MOVSL // arg 4 - oldlenp 356 MOVSL // arg 5 - newp 357 MOVSL // arg 6 - newlen 358 MOVL $202, AX // sys___sysctl 359 INT $0x80 360 JAE 4(PC) 361 NEGL AX 362 MOVL AX, ret+24(FP) 363 RET 364 MOVL $0, AX 365 MOVL AX, ret+24(FP) 366 RET 367 368 TEXT runtimeosyield(SB),NOSPLIT,$-4 369 MOVL $331, AX // sys_sched_yield 370 INT $0x80 371 RET 372 373 TEXT runtimesigprocmask(SB),NOSPLIT,$16 374 MOVL $0, 0(SP) // syscall gap 375 MOVL how+0(FP), AX // arg 1 - how 376 MOVL AX, 4(SP) 377 MOVL new+4(FP), AX 378 MOVL AX, 8(SP) // arg 2 - set 379 MOVL old+8(FP), AX 380 MOVL AX, 12(SP) // arg 3 - oset 381 MOVL $340, AX // sys_sigprocmask 382 INT $0x80 383 JAE 2(PC) 384 MOVL $0xf1, 0xf1 // crash 385 RET 386 387 // int32 runtimekqueue(void); 388 TEXT runtimekqueue(SB),NOSPLIT,$0 389 MOVL $362, AX 390 INT $0x80 391 JAE 2(PC) 392 NEGL AX 393 MOVL AX, ret+0(FP) 394 RET 395 396 // int32 runtimekevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout); 397 TEXT runtimekevent(SB),NOSPLIT,$0 398 MOVL $363, AX 399 INT $0x80 400 JAE 2(PC) 401 NEGL AX 402 MOVL AX, ret+24(FP) 403 RET 404 405 // int32 runtimecloseonexec(int32 fd); 406 TEXT runtimecloseonexec(SB),NOSPLIT,$32 407 MOVL $92, AX // fcntl 408 // 0(SP) is where the caller PC would be; kernel skips it 409 MOVL fd+0(FP), BX 410 MOVL BX, 4(SP) // fd 411 MOVL $2, 8(SP) // F_SETFD 412 MOVL $1, 12(SP) // FD_CLOEXEC 413 INT $0x80 414 JAE 2(PC) 415 NEGL AX 416 RET 417 418 // func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32 419 TEXT runtimecpuset_getaffinity(SB), NOSPLIT, $0-28 420 MOVL $487, AX 421 INT $0x80 422 JAE 2(PC) 423 NEGL AX 424 MOVL AX, ret+24(FP) 425 RET 426 427 GLOBL runtimetlsoffset(SB),NOPTR,$4 428