1 // Copyright 2013 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 #include "go_asm.h" 6 #include "go_tls.h" 7 #include "textflag.h" 8 #include "syscall_nacl.h" 9 10 #define NACL_SYSCALL(code) \ 11 MOVL $(0x10000 + ((code)<<5)), AX; CALL AX 12 13 TEXT runtimeexit(SB),NOSPLIT,$4 14 MOVL code+0(FP), AX 15 MOVL AX, 0(SP) 16 NACL_SYSCALL(SYS_exit) 17 JMP 0(PC) 18 19 TEXT runtimeexit1(SB),NOSPLIT,$4 20 MOVL code+0(FP), AX 21 MOVL AX, 0(SP) 22 NACL_SYSCALL(SYS_thread_exit) 23 RET 24 25 TEXT runtimeopen(SB),NOSPLIT,$12 26 MOVL name+0(FP), AX 27 MOVL AX, 0(SP) 28 MOVL mode+4(FP), AX 29 MOVL AX, 4(SP) 30 MOVL perm+8(FP), AX 31 MOVL AX, 8(SP) 32 NACL_SYSCALL(SYS_open) 33 MOVL AX, ret+12(FP) 34 RET 35 36 TEXT runtimeclosefd(SB),NOSPLIT,$4 37 MOVL fd+0(FP), AX 38 MOVL AX, 0(SP) 39 NACL_SYSCALL(SYS_close) 40 MOVL AX, ret+4(FP) 41 RET 42 43 TEXT runtimeread(SB),NOSPLIT,$12 44 MOVL fd+0(FP), AX 45 MOVL AX, 0(SP) 46 MOVL p+4(FP), AX 47 MOVL AX, 4(SP) 48 MOVL n+8(FP), AX 49 MOVL AX, 8(SP) 50 NACL_SYSCALL(SYS_read) 51 MOVL AX, ret+12(FP) 52 RET 53 54 TEXT syscallnaclWrite(SB), NOSPLIT, $16-16 55 MOVL arg1+0(FP), DI 56 MOVL arg2+4(FP), SI 57 MOVL arg3+8(FP), DX 58 MOVL DI, 0(SP) 59 MOVL SI, 4(SP) 60 MOVL DX, 8(SP) 61 CALL runtimewrite(SB) 62 MOVL AX, ret+16(FP) 63 RET 64 65 TEXT runtimewrite(SB),NOSPLIT,$12 66 MOVL fd+0(FP), AX 67 MOVL AX, 0(SP) 68 MOVL p+4(FP), AX 69 MOVL AX, 4(SP) 70 MOVL n+8(FP), AX 71 MOVL AX, 8(SP) 72 NACL_SYSCALL(SYS_write) 73 MOVL AX, ret+12(FP) 74 RET 75 76 TEXT runtimenacl_exception_stack(SB),NOSPLIT,$8 77 MOVL p+0(FP), AX 78 MOVL AX, 0(SP) 79 MOVL size+4(FP), AX 80 MOVL AX, 4(SP) 81 NACL_SYSCALL(SYS_exception_stack) 82 MOVL AX, ret+8(FP) 83 RET 84 85 TEXT runtimenacl_exception_handler(SB),NOSPLIT,$8 86 MOVL fn+0(FP), AX 87 MOVL AX, 0(SP) 88 MOVL arg+4(FP), AX 89 MOVL AX, 4(SP) 90 NACL_SYSCALL(SYS_exception_handler) 91 MOVL AX, ret+8(FP) 92 RET 93 94 TEXT runtimenacl_sem_create(SB),NOSPLIT,$4 95 MOVL flag+0(FP), AX 96 MOVL AX, 0(SP) 97 NACL_SYSCALL(SYS_sem_create) 98 MOVL AX, ret+4(FP) 99 RET 100 101 TEXT runtimenacl_sem_wait(SB),NOSPLIT,$4 102 MOVL sem+0(FP), AX 103 MOVL AX, 0(SP) 104 NACL_SYSCALL(SYS_sem_wait) 105 MOVL AX, ret+4(FP) 106 RET 107 108 TEXT runtimenacl_sem_post(SB),NOSPLIT,$4 109 MOVL sem+0(FP), AX 110 MOVL AX, 0(SP) 111 NACL_SYSCALL(SYS_sem_post) 112 MOVL AX, ret+4(FP) 113 RET 114 115 TEXT runtimenacl_mutex_create(SB),NOSPLIT,$4 116 MOVL flag+0(FP), AX 117 MOVL AX, 0(SP) 118 NACL_SYSCALL(SYS_mutex_create) 119 MOVL AX, ret+4(FP) 120 RET 121 122 TEXT runtimenacl_mutex_lock(SB),NOSPLIT,$4 123 MOVL mutex+0(FP), AX 124 MOVL AX, 0(SP) 125 NACL_SYSCALL(SYS_mutex_lock) 126 MOVL AX, ret+4(FP) 127 RET 128 129 TEXT runtimenacl_mutex_trylock(SB),NOSPLIT,$4 130 MOVL mutex+0(FP), AX 131 MOVL AX, 0(SP) 132 NACL_SYSCALL(SYS_mutex_trylock) 133 MOVL AX, ret+4(FP) 134 RET 135 136 TEXT runtimenacl_mutex_unlock(SB),NOSPLIT,$4 137 MOVL mutex+0(FP), AX 138 MOVL AX, 0(SP) 139 NACL_SYSCALL(SYS_mutex_unlock) 140 MOVL AX, ret+4(FP) 141 RET 142 143 TEXT runtimenacl_cond_create(SB),NOSPLIT,$4 144 MOVL flag+0(FP), AX 145 MOVL AX, 0(SP) 146 NACL_SYSCALL(SYS_cond_create) 147 MOVL AX, ret+4(FP) 148 RET 149 150 TEXT runtimenacl_cond_wait(SB),NOSPLIT,$8 151 MOVL cond+0(FP), AX 152 MOVL AX, 0(SP) 153 MOVL n+4(FP), AX 154 MOVL AX, 4(SP) 155 NACL_SYSCALL(SYS_cond_wait) 156 MOVL AX, ret+8(FP) 157 RET 158 159 TEXT runtimenacl_cond_signal(SB),NOSPLIT,$4 160 MOVL cond+0(FP), AX 161 MOVL AX, 0(SP) 162 NACL_SYSCALL(SYS_cond_signal) 163 MOVL AX, ret+4(FP) 164 RET 165 166 TEXT runtimenacl_cond_broadcast(SB),NOSPLIT,$4 167 MOVL cond+0(FP), AX 168 MOVL AX, 0(SP) 169 NACL_SYSCALL(SYS_cond_broadcast) 170 MOVL AX, ret+4(FP) 171 RET 172 173 TEXT runtimenacl_cond_timed_wait_abs(SB),NOSPLIT,$12 174 MOVL cond+0(FP), AX 175 MOVL AX, 0(SP) 176 MOVL lock+4(FP), AX 177 MOVL AX, 4(SP) 178 MOVL ts+8(FP), AX 179 MOVL AX, 8(SP) 180 NACL_SYSCALL(SYS_cond_timed_wait_abs) 181 MOVL AX, ret+12(FP) 182 RET 183 184 TEXT runtimenacl_thread_create(SB),NOSPLIT,$16 185 MOVL fn+0(FP), AX 186 MOVL AX, 0(SP) 187 MOVL stk+4(FP), AX 188 MOVL AX, 4(SP) 189 MOVL tls+8(FP), AX 190 MOVL AX, 8(SP) 191 MOVL xx+12(FP), AX 192 MOVL AX, 12(SP) 193 NACL_SYSCALL(SYS_thread_create) 194 MOVL AX, ret+16(FP) 195 RET 196 197 TEXT runtimemstart_nacl(SB),NOSPLIT,$0 198 JMP runtimemstart(SB) 199 200 TEXT runtimenacl_nanosleep(SB),NOSPLIT,$8 201 MOVL ts+0(FP), AX 202 MOVL AX, 0(SP) 203 MOVL extra+4(FP), AX 204 MOVL AX, 4(SP) 205 NACL_SYSCALL(SYS_nanosleep) 206 MOVL AX, ret+8(FP) 207 RET 208 209 TEXT runtimeosyield(SB),NOSPLIT,$0 210 NACL_SYSCALL(SYS_sched_yield) 211 RET 212 213 TEXT runtimemmap(SB),NOSPLIT,$32 214 MOVL addr+0(FP), AX 215 MOVL AX, 0(SP) 216 MOVL n+4(FP), AX 217 MOVL AX, 4(SP) 218 MOVL prot+8(FP), AX 219 MOVL AX, 8(SP) 220 MOVL flags+12(FP), AX 221 MOVL AX, 12(SP) 222 MOVL fd+16(FP), AX 223 MOVL AX, 16(SP) 224 MOVL off+20(FP), AX 225 MOVL AX, 24(SP) 226 MOVL $0, 28(SP) 227 LEAL 24(SP), AX 228 MOVL AX, 20(SP) 229 NACL_SYSCALL(SYS_mmap) 230 MOVL AX, ret+24(FP) 231 RET 232 233 TEXT timenow(SB),NOSPLIT,$20 234 MOVL $0, 0(SP) // real time clock 235 LEAL 8(SP), AX 236 MOVL AX, 4(SP) // timespec 237 NACL_SYSCALL(SYS_clock_gettime) 238 MOVL 8(SP), AX // low 32 sec 239 MOVL 12(SP), CX // high 32 sec 240 MOVL 16(SP), BX // nsec 241 242 // sec is in AX, nsec in BX 243 MOVL AX, sec+0(FP) 244 MOVL CX, sec+4(FP) 245 MOVL BX, nsec+8(FP) 246 RET 247 248 TEXT syscallnow(SB),NOSPLIT,$0 249 JMP timenow(SB) 250 251 TEXT runtimenacl_clock_gettime(SB),NOSPLIT,$8 252 MOVL arg1+0(FP), AX 253 MOVL AX, 0(SP) 254 MOVL arg2+4(FP), AX 255 MOVL AX, 4(SP) 256 NACL_SYSCALL(SYS_clock_gettime) 257 MOVL AX, ret+8(FP) 258 RET 259 260 TEXT runtimenanotime(SB),NOSPLIT,$20 261 MOVL $0, 0(SP) // real time clock 262 LEAL 8(SP), AX 263 MOVL AX, 4(SP) // timespec 264 NACL_SYSCALL(SYS_clock_gettime) 265 MOVL 8(SP), AX // low 32 sec 266 MOVL 16(SP), BX // nsec 267 268 // sec is in AX, nsec in BX 269 // convert to DX:AX nsec 270 MOVL $1000000000, CX 271 MULL CX 272 ADDL BX, AX 273 ADCL $0, DX 274 275 MOVL AX, ret_lo+0(FP) 276 MOVL DX, ret_hi+4(FP) 277 RET 278 279 TEXT runtimesetldt(SB),NOSPLIT,$8 280 MOVL addr+4(FP), BX // aka base 281 ADDL $0x8, BX 282 MOVL BX, 0(SP) 283 NACL_SYSCALL(SYS_tls_init) 284 RET 285 286 TEXT runtimesigtramp(SB),NOSPLIT,$0 287 get_tls(CX) 288 289 // check that g exists 290 MOVL g(CX), DI 291 CMPL DI, $0 292 JNE 6(PC) 293 MOVL $11, BX 294 MOVL $0, 0(SP) 295 MOVL $runtimebadsignal(SB), AX 296 CALL AX 297 JMP ret 298 299 // save g 300 MOVL DI, 20(SP) 301 302 // g = m->gsignal 303 MOVL g_m(DI), BX 304 MOVL m_gsignal(BX), BX 305 MOVL BX, g(CX) 306 307 // copy arguments for sighandler 308 MOVL $11, 0(SP) // signal 309 MOVL $0, 4(SP) // siginfo 310 LEAL ctxt+4(FP), AX 311 MOVL AX, 8(SP) // context 312 MOVL DI, 12(SP) // g 313 314 CALL runtimesighandler(SB) 315 316 // restore g 317 get_tls(CX) 318 MOVL 20(SP), BX 319 MOVL BX, g(CX) 320 321 ret: 322 // Enable exceptions again. 323 NACL_SYSCALL(SYS_exception_clear_flag) 324 325 // NaCl has abdicated its traditional operating system responsibility 326 // and declined to implement 'sigreturn'. Instead the only way to return 327 // to the execution of our program is to restore the registers ourselves. 328 // Unfortunately, that is impossible to do with strict fidelity, because 329 // there is no way to do the final update of PC that ends the sequence 330 // without either (1) jumping to a register, in which case the register ends 331 // holding the PC value instead of its intended value or (2) storing the PC 332 // on the stack and using RET, which imposes the requirement that SP is 333 // valid and that is okay to smash the word below it. The second would 334 // normally be the lesser of the two evils, except that on NaCl, the linker 335 // must rewrite RET into "POP reg; AND $~31, reg; JMP reg", so either way 336 // we are going to lose a register as a result of the incoming signal. 337 // Similarly, there is no way to restore EFLAGS; the usual way is to use 338 // POPFL, but NaCl rejects that instruction. We could inspect the bits and 339 // execute a sequence of instructions designed to recreate those flag 340 // settings, but that's a lot of work. 341 // 342 // Thankfully, Go's signal handlers never try to return directly to the 343 // executing code, so all the registers and EFLAGS are dead and can be 344 // smashed. The only registers that matter are the ones that are setting 345 // up for the simulated call that the signal handler has created. 346 // Today those registers are just PC and SP, but in case additional registers 347 // are relevant in the future (for example DX is the Go func context register) 348 // we restore as many registers as possible. 349 // 350 // We smash BP, because that's what the linker smashes during RET. 351 // 352 LEAL ctxt+4(FP), BP 353 ADDL $64, BP 354 MOVL 0(BP), AX 355 MOVL 4(BP), CX 356 MOVL 8(BP), DX 357 MOVL 12(BP), BX 358 MOVL 16(BP), SP 359 // 20(BP) is saved BP, never to be seen again 360 MOVL 24(BP), SI 361 MOVL 28(BP), DI 362 // 36(BP) is saved EFLAGS, never to be seen again 363 MOVL 32(BP), BP // saved PC 364 JMP BP 365 366 // func getRandomData([]byte) 367 TEXT runtimegetRandomData(SB),NOSPLIT,$8-12 368 MOVL buf+0(FP), AX 369 MOVL AX, 0(SP) 370 MOVL len+4(FP), AX 371 MOVL AX, 4(SP) 372 NACL_SYSCALL(SYS_get_random_bytes) 373 RET 374