diff options
Diffstat (limited to 'src/pkg/runtime')
| -rw-r--r-- | src/pkg/runtime/amd64/asm.s | 5 | ||||
| -rw-r--r-- | src/pkg/runtime/darwin/amd64/rt0.s | 1 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/amd64/defs.h | 157 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/amd64/rt0.s | 9 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/amd64/signal.c | 117 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/amd64/sys.s | 125 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/defs.c | 49 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/os.h | 19 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/signals.h | 48 | ||||
| -rw-r--r-- | src/pkg/runtime/freebsd/thread.c | 162 | ||||
| -rw-r--r-- | src/pkg/runtime/linux/amd64/rt0.s | 1 |
11 files changed, 690 insertions, 3 deletions
diff --git a/src/pkg/runtime/amd64/asm.s b/src/pkg/runtime/amd64/asm.s index df81c0eb79..aee4e9a3f7 100644 --- a/src/pkg/runtime/amd64/asm.s +++ b/src/pkg/runtime/amd64/asm.s @@ -5,10 +5,9 @@ #include "amd64/asm.h" TEXT _rt0_amd64(SB),7,$-8 - // copy arguments forward on an even stack - MOVQ 0(SP), AX // argc - LEAQ 8(SP), BX // argv + MOVQ 0(DI), AX // argc + LEAQ 8(DI), BX // argv SUBQ $(4*8+7), SP // 2args 2auto ANDQ $~7, SP MOVQ AX, 16(SP) diff --git a/src/pkg/runtime/darwin/amd64/rt0.s b/src/pkg/runtime/darwin/amd64/rt0.s index 0a0011781d..1b706365ac 100644 --- a/src/pkg/runtime/darwin/amd64/rt0.s +++ b/src/pkg/runtime/darwin/amd64/rt0.s @@ -6,4 +6,5 @@ TEXT _rt0_amd64_darwin(SB),7,$-8 MOVQ $_rt0_amd64(SB), AX + MOVQ SP, DI JMP AX diff --git a/src/pkg/runtime/freebsd/amd64/defs.h b/src/pkg/runtime/freebsd/amd64/defs.h new file mode 100644 index 0000000000..06efcc27ae --- /dev/null +++ b/src/pkg/runtime/freebsd/amd64/defs.h @@ -0,0 +1,157 @@ +// godefs -f -m64 freebsd/defs.c + +// MACHINE GENERATED - DO NOT EDIT. + +// Constants +enum { + PROT_NONE = 0, + PROT_READ = 0x1, + PROT_WRITE = 0x2, + PROT_EXEC = 0x4, + MAP_ANON = 0x1000, + MAP_PRIVATE = 0x2, + SA_SIGINFO = 0x40, + SA_RESTART = 0x2, + SA_ONSTACK = 0x1, + UMTX_OP_WAIT = 0x2, + UMTX_OP_WAKE = 0x3, + EINTR = 0x4, +}; + +// Types +#pragma pack on + +typedef struct Sigaltstack Sigaltstack; +struct Sigaltstack { + int8 *ss_sp; + uint64 ss_size; + int32 ss_flags; + byte pad0[4]; +}; + +typedef struct Sigset Sigset; +struct Sigset { + uint32 __bits[4]; +}; + +typedef union Sigval Sigval; +union Sigval { + int32 sival_int; + void *sival_ptr; + int32 sigval_int; + void *sigval_ptr; +}; + +typedef struct StackT StackT; +struct StackT { + int8 *ss_sp; + uint64 ss_size; + int32 ss_flags; + byte pad0[4]; +}; + +typedef struct Siginfo Siginfo; +struct Siginfo { + int32 si_signo; + int32 si_errno; + int32 si_code; + int32 si_pid; + uint32 si_uid; + int32 si_status; + void *si_addr; + Sigval si_value; + byte _reason[40]; +}; + +typedef struct Mcontext Mcontext; +struct Mcontext { + int64 mc_onstack; + int64 mc_rdi; + int64 mc_rsi; + int64 mc_rdx; + int64 mc_rcx; + int64 mc_r8; + int64 mc_r9; + int64 mc_rax; + int64 mc_rbx; + int64 mc_rbp; + int64 mc_r10; + int64 mc_r11; + int64 mc_r12; + int64 mc_r13; + int64 mc_r14; + int64 mc_r15; + uint32 mc_trapno; + uint16 mc_fs; + uint16 mc_gs; + int64 mc_addr; + uint32 mc_flags; + uint16 mc_es; + uint16 mc_ds; + int64 mc_err; + int64 mc_rip; + int64 mc_cs; + int64 mc_rflags; + int64 mc_rsp; + int64 mc_ss; + int64 mc_len; + int64 mc_fpformat; + int64 mc_ownedfp; + int64 mc_fpstate[64]; + int64 mc_fsbase; + int64 mc_gsbase; + int64 mc_spare[6]; +}; + +typedef struct Ucontext Ucontext; +struct Ucontext { + Sigset uc_sigmask; + Mcontext uc_mcontext; + Ucontext *uc_link; + StackT uc_stack; + int32 uc_flags; + int32 __spare__[4]; + byte pad0[12]; +}; + +typedef struct Sigcontext Sigcontext; +struct Sigcontext { + Sigset sc_mask; + int64 sc_onstack; + int64 sc_rdi; + int64 sc_rsi; + int64 sc_rdx; + int64 sc_rcx; + int64 sc_r8; + int64 sc_r9; + int64 sc_rax; + int64 sc_rbx; + int64 sc_rbp; + int64 sc_r10; + int64 sc_r11; + int64 sc_r12; + int64 sc_r13; + int64 sc_r14; + int64 sc_r15; + int32 sc_trapno; + int16 sc_fs; + int16 sc_gs; + int64 sc_addr; + int32 sc_flags; + int16 sc_es; + int16 sc_ds; + int64 sc_err; + int64 sc_rip; + int64 sc_cs; + int64 sc_rflags; + int64 sc_rsp; + int64 sc_ss; + int64 sc_len; + int64 sc_fpformat; + int64 sc_ownedfp; + int64 sc_fpstate[64]; + int64 sc_fsbase; + int64 sc_gsbase; + int64 sc_spare[6]; +}; +#pragma pack off diff --git a/src/pkg/runtime/freebsd/amd64/rt0.s b/src/pkg/runtime/freebsd/amd64/rt0.s new file mode 100644 index 0000000000..7903b7ccca --- /dev/null +++ b/src/pkg/runtime/freebsd/amd64/rt0.s @@ -0,0 +1,9 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Darwin and Linux use the same linkage to main + +TEXT _rt0_amd64_freebsd(SB),7,$-8 + MOVQ $_rt0_amd64(SB), DX + JMP DX diff --git a/src/pkg/runtime/freebsd/amd64/signal.c b/src/pkg/runtime/freebsd/amd64/signal.c new file mode 100644 index 0000000000..08d89727da --- /dev/null +++ b/src/pkg/runtime/freebsd/amd64/signal.c @@ -0,0 +1,117 @@ +#include "runtime.h" +#include "defs.h" +#include "signals.h" +#include "os.h" + +extern void sigtramp(void); + +typedef struct sigaction { + union { + void (*__sa_handler)(int32); + void (*__sa_sigaction)(int32, Siginfo*, void *); + } __sigaction_u; /* signal handler */ + int32 sa_flags; /* see signal options below */ + int64 sa_mask; /* signal mask to apply */ +} Sigaction; + +void +dumpregs(Sigcontext *r) +{ + printf("rax %X\n", r->sc_rax); + printf("rbx %X\n", r->sc_rbx); + printf("rcx %X\n", r->sc_rcx); + printf("rdx %X\n", r->sc_rdx); + printf("rdi %X\n", r->sc_rdi); + printf("rsi %X\n", r->sc_rsi); + printf("rbp %X\n", r->sc_rbp); + printf("rsp %X\n", r->sc_rsp); + printf("r8 %X\n", r->sc_r8 ); + printf("r9 %X\n", r->sc_r9 ); + printf("r10 %X\n", r->sc_r10); + printf("r11 %X\n", r->sc_r11); + printf("r12 %X\n", r->sc_r12); + printf("r13 %X\n", r->sc_r13); + printf("r14 %X\n", r->sc_r14); + printf("r15 %X\n", r->sc_r15); + printf("rip %X\n", r->sc_rip); + printf("rflags %X\n", r->sc_flags); + printf("cs %X\n", (uint64)r->sc_cs); + printf("fs %X\n", (uint64)r->sc_fsbase); + printf("gs %X\n", (uint64)r->sc_gsbase); +} + +void +sighandler(int32 sig, Siginfo* info, void* context) +{ + Ucontext *uc; + Mcontext *mc; + Sigcontext *sc; + + if(panicking) // traceback already printed + exit(2); + panicking = 1; + + uc = context; + mc = &uc->uc_mcontext; + sc = (Sigcontext*)mc; // same layout, more conveient names + + if(sig < 0 || sig >= NSIG) + printf("Signal %d\n", sig); + else + printf("%s\n", sigtab[sig].name); + + printf("Faulting address: %p\n", info->si_addr); + printf("PC=%X\n", sc->sc_rip); + printf("\n"); + + if(gotraceback()){ + traceback((void*)sc->sc_rip, (void*)sc->sc_rsp, (void*)sc->sc_r15); + tracebackothers((void*)sc->sc_r15); + dumpregs(sc); + } + + breakpoint(); + exit(2); +} + +void +sigignore(void) +{ +} + +void +signalstack(byte *p, int32 n) +{ + Sigaltstack st; + + st.ss_sp = (int8*)p; + st.ss_size = n; + st.ss_flags = 0; + sigaltstack(&st, nil); +} + +void +initsig(void) +{ + static Sigaction sa; + + int32 i; + sa.sa_flags |= SA_ONSTACK | SA_SIGINFO; + sa.sa_mask = ~0x0ull; + + for(i = 0; i < NSIG; i++) { + if(sigtab[i].flags) { + if(sigtab[i].flags & SigCatch) + sa.__sigaction_u.__sa_handler = (void*) sigtramp; + else + sa.__sigaction_u.__sa_handler = (void*) sigignore; + + if(sigtab[i].flags & SigRestart) + sa.sa_flags |= SA_RESTART; + else + sa.sa_flags &= ~SA_RESTART; + + sigaction(i, &sa, nil); + } + } +} diff --git a/src/pkg/runtime/freebsd/amd64/sys.s b/src/pkg/runtime/freebsd/amd64/sys.s new file mode 100644 index 0000000000..1b62468105 --- /dev/null +++ b/src/pkg/runtime/freebsd/amd64/sys.s @@ -0,0 +1,125 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// System calls and other sys.stuff for AMD64, FreeBSD +// /usr/src/sys/kern/syscalls.master for syscall numbers. +// + +#include "amd64/asm.h" + +TEXT sys_umtx_op(SB),7,$0 + MOVQ 8(SP), DI + MOVL 16(SP), SI + MOVL 20(SP), DX + MOVQ 24(SP), R10 + MOVQ 32(SP), R8 + MOVL $454, AX + SYSCALL + RET + +TEXT thr_new(SB),7,$0 + MOVQ 8(SP), DI + MOVQ 16(SP), SI + MOVL $455, AX + SYSCALL + RET + +TEXT thr_start(SB),7,$0 + MOVQ DI, m + MOVQ m_g0(m), g + CALL mstart(SB) + MOVQ 0, AX // crash (not reached) + + +// Exit the entire program (like C exit) +TEXT exit(SB),7,$-8 + MOVL 8(SP), DI // arg 1 exit status + MOVL $1, AX + SYSCALL + CALL notok(SB) + RET + +TEXT exit1(SB),7,$-8 + MOVQ 8(SP), DI // arg 1 exit status + MOVL $431, AX + SYSCALL + CALL notok(SB) + RET + +TEXT write(SB),7,$-8 + MOVL 8(SP), DI // arg 1 fd + MOVQ 16(SP), SI // arg 2 buf + MOVL 24(SP), DX // arg 3 count + MOVL $4, AX + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET + +TEXT sigaction(SB),7,$-8 + MOVL 8(SP), DI // arg 1 sig + MOVQ 16(SP), SI // arg 2 act + MOVQ 24(SP), DX // arg 3 oact + MOVL $416, AX + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET + +TEXT sigtramp(SB),7,$24-16 + MOVQ m_gsignal(m), g + MOVQ DI, 0(SP) + MOVQ SI, 8(SP) + MOVQ DX, 16(SP) + CALL sighandler(SB) + RET + +TEXT runtime·mmap(SB),7,$-8 + MOVQ 8(SP), DI // arg 1 addr + MOVL 16(SP), SI // arg 2 len + MOVL 20(SP), DX // arg 3 prot + MOVL 24(SP), R10 // arg 4 flags + MOVL 28(SP), R8 // arg 5 fid + MOVL 32(SP), R9 // arg 6 offset + MOVL $477, AX + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET + +TEXT notok(SB),7,$-8 + MOVL $0xf1, BP + MOVQ BP, (BP) + RET + +TEXT runtime·memclr(SB),7,$-8 + MOVQ 8(SP), DI // arg 1 addr + MOVL 16(SP), CX // arg 2 count + ADDL $7, CX + SHRL $3, CX + MOVQ $0, AX + CLD + REP + STOSQ + RET + +TEXT runtime·getcallerpc+0(SB),7,$0 + MOVQ x+0(FP),AX // addr of first arg + MOVQ -8(AX),AX // get calling pc + RET + +TEXT runtime·setcallerpc+0(SB),7,$0 + MOVQ x+0(FP),AX // addr of first arg + MOVQ x+8(FP), BX + MOVQ BX, -8(AX) // set calling pc + RET + +TEXT sigaltstack(SB),7,$-8 + MOVQ new+8(SP), DI + MOVQ old+16(SP), SI + MOVQ $53, AX + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET diff --git a/src/pkg/runtime/freebsd/defs.c b/src/pkg/runtime/freebsd/defs.c new file mode 100644 index 0000000000..414e7cd765 --- /dev/null +++ b/src/pkg/runtime/freebsd/defs.c @@ -0,0 +1,49 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Input to godefs. + * + godefs -f -m64 defs.c >amd64/defs.h + godefs defs.c >386/defs.h + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <signal.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/ucontext.h> +#include <sys/umtx.h> +#include <sys/_sigset.h> + +enum { + $PROT_NONE = PROT_NONE, + $PROT_READ = PROT_READ, + $PROT_WRITE = PROT_WRITE, + $PROT_EXEC = PROT_EXEC, + + $MAP_ANON = MAP_ANON, + $MAP_PRIVATE = MAP_PRIVATE, + + $SA_SIGINFO = SA_SIGINFO, + $SA_RESTART = SA_RESTART, + $SA_ONSTACK = SA_ONSTACK, + + $UMTX_OP_WAIT = UMTX_OP_WAIT, + $UMTX_OP_WAKE = UMTX_OP_WAKE, + + $EINTR = EINTR, +}; + +typedef struct sigaltstack $Sigaltstack; +typedef struct __sigset $Sigset; +typedef union sigval $Sigval; +typedef stack_t $StackT; + +typedef siginfo_t $Siginfo; + +typedef mcontext_t $Mcontext; +typedef ucontext_t $Ucontext; +typedef struct sigcontext $Sigcontext; diff --git a/src/pkg/runtime/freebsd/os.h b/src/pkg/runtime/freebsd/os.h new file mode 100644 index 0000000000..ec91500b7b --- /dev/null +++ b/src/pkg/runtime/freebsd/os.h @@ -0,0 +1,19 @@ +// FreeBSD-specific system calls +int32 ksem_init(uint64 *, uint32); +int32 ksem_wait(uint32); +int32 ksem_destroy(uint32); +int32 ksem_post(uint32); + +struct thr_param { + void (*start_func)(void *); /* thread entry function. */ + void *arg; /* argument for entry function. */ + byte *stack_base; /* stack base address. */ + int64 stack_size; /* stack size. */ + byte *tls_base; /* tls base address. */ + int64 tls_size; /* tls size. */ + int64 *child_tid; /* address to store new TID. */ + int64 *parent_tid; /* parent accesses the new TID here. */ + int32 flags; /* thread flags. */ + void *spare[4]; /* TODO: cpu affinity mask etc. */ +}; +int32 thr_new(struct thr_param*, uint64); diff --git a/src/pkg/runtime/freebsd/signals.h b/src/pkg/runtime/freebsd/signals.h new file mode 100644 index 0000000000..c566481e05 --- /dev/null +++ b/src/pkg/runtime/freebsd/signals.h @@ -0,0 +1,48 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#define C SigCatch +#define I SigIgnore +#define R SigRestart + +static SigTab sigtab[] = { + /* 0 */ 0, "SIGNONE: no trap", + /* 1 */ 0, "SIGHUP: terminal line hangup", + /* 2 */ 0, "SIGINT: interrupt", + /* 3 */ C, "SIGQUIT: quit", + /* 4 */ C, "SIGILL: illegal instruction", + /* 5 */ C, "SIGTRAP: trace trap", + /* 6 */ C, "SIGABRT: abort", + /* 7 */ C, "SIGEMT: EMT instruction", + /* 8 */ C, "SIGFPE: floating-point exception", + /* 9 */ 0, "SIGKILL: kill", + /* 10 */ C, "SIGBUS: bus error", + /* 11 */ C, "SIGSEGV: segmentation violation", + /* 12 */ C, "SIGSYS: bad system call", + /* 13 */ I, "SIGPIPE: write to broken pipe", + /* 14 */ 0, "SIGALRM: alarm clock", + /* 15 */ 0, "SIGTERM: termination", + /* 16 */ 0, "SIGURG: urgent condition on socket", + /* 17 */ 0, "SIGSTOP: stop, unblockable", + /* 18 */ 0, "SIGTSTP: stop from tty", + /* 19 */ 0, "SIGCONT: continue", + /* 20 */ I+R, "SIGCHLD: child status has changed", + /* 21 */ 0, "SIGTTIN: background read from tty", + /* 22 */ 0, "SIGTTOU: background write to tty", + /* 23 */ 0, "SIGIO: i/o now possible", + /* 24 */ 0, "SIGXCPU: cpu limit exceeded", + /* 25 */ 0, "SIGXFSZ: file size limit exceeded", + /* 26 */ 0, "SIGVTALRM: virtual alarm clock", + /* 27 */ 0, "SIGPROF: profiling alarm clock", + /* 28 */ I+R, "SIGWINCH: window size change", + /* 29 */ 0, "SIGINFO: information request", + /* 30 */ 0, "SIGUSR1: user-defined signal 1", + /* 31 */ 0, "SIGUSR2: user-defined signal 2", + /* 32 */ 0, "SIGTHR: reserved", +}; +#undef C +#undef I +#undef R + +#define NSIG 33 diff --git a/src/pkg/runtime/freebsd/thread.c b/src/pkg/runtime/freebsd/thread.c new file mode 100644 index 0000000000..e7cd707d03 --- /dev/null +++ b/src/pkg/runtime/freebsd/thread.c @@ -0,0 +1,162 @@ +// Use of this source file is governed by a BSD-style +// license that can be found in the LICENSE file.` + +#include "runtime.h" +#include "defs.h" +#include "signals.h" +#include "os.h" + +// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and +// thus the code is largely similar. See linux/thread.c for comments. + +static void +umtx_wait(uint32 *addr, uint32 val) +{ + int32 ret; + + ret = sys_umtx_op(addr, UMTX_OP_WAIT, val, nil, nil); + if(ret >= 0 || ret == -EINTR) + return; + + printf("umtx_wait addr=%p val=%d ret=%d\n", addr, val, ret); + *(int32*)0x1005 = 0x1005; +} + +static void +umtx_wake(uint32 *addr) +{ + int32 ret; + + ret = sys_umtx_op(addr, UMTX_OP_WAKE, 1, nil, nil); + if(ret >= 0) + return; + + printf("umtx_wake addr=%p ret=%d\n", addr, ret); + *(int32*)0x1006 = 0x1006; +} + +// See linux/thread.c for comments about the algorithm. +static void +umtx_lock(Lock *l) +{ + uint32 v; + +again: + v = l->key; + if((v&1) == 0){ + if(cas(&l->key, v, v|1)) + return; + goto again; + } + + if(!cas(&l->key, v, v+2)) + goto again; + + umtx_wait(&l->key, v+2); + + for(;;){ + v = l->key; + if(v < 2) + throw("bad lock key"); + if(cas(&l->key, v, v-2)) + break; + } + + goto again; +} + +static void +umtx_unlock(Lock *l) +{ + uint32 v; + +again: + v = l->key; + if((v&1) == 0) + throw("unlock of unlocked lock"); + if(!cas(&l->key, v, v&~1)) + goto again; + + if(v&~1) + umtx_wake(&l->key); +} + +void +lock(Lock *l) +{ + if(m->locks < 0) + throw("lock count"); + m->locks++; + umtx_lock(l); +} + +void +unlock(Lock *l) +{ + m->locks--; + if(m->locks < 0) + throw("lock count"); + umtx_unlock(l); +} + +// Event notifications. +void +noteclear(Note *n) +{ + n->lock.key = 0; + umtx_lock(&n->lock); +} + +void +notesleep(Note *n) +{ + umtx_lock(&n->lock); + umtx_unlock(&n->lock); +} + +void +notewakeup(Note *n) +{ + umtx_unlock(&n->lock); +} + +void thr_start(void*); + +void +newosproc(M *m, G *g, void *stk, void (*fn)(void)) +{ + struct thr_param param; + + USED(fn); // thr_start assumes fn == mstart + USED(g); // thr_start assumes g == m->g0 + + if(0){ + printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n", + stk, m, g, fn, m->id, m->tls[0], &m); + } + + runtime_memclr((byte*)¶m, sizeof param); + + param.start_func = thr_start; + param.arg = m; + param.stack_base = stk; + param.stack_size = g->stackbase - g->stackguard + 256; + param.child_tid = (int64*)&m->procid; + param.parent_tid = nil; + + thr_new(¶m, sizeof param); +} + +void +osinit(void) +{ +} + +// Called to initialize a new m (including the bootstrap m). +void +minit(void) +{ + // Initialize signal handling + m->gsignal = malg(32*1024); + signalstack(m->gsignal->stackguard, 32*1024); +} diff --git a/src/pkg/runtime/linux/amd64/rt0.s b/src/pkg/runtime/linux/amd64/rt0.s index e04866458a..6b1b297752 100644 --- a/src/pkg/runtime/linux/amd64/rt0.s +++ b/src/pkg/runtime/linux/amd64/rt0.s @@ -11,6 +11,7 @@ TEXT _rt0_amd64_linux(SB),7,$-8 CALL AX MOVQ $_rt0_amd64(SB), AX + MOVQ SP, DI JMP AX GLOBL initcgo(SB), $8 |
