diff --git a/src/pkg/runtime/openbsd/386/rt0.s b/src/pkg/runtime/openbsd/386/rt0.s new file mode 100644 index 0000000000..e7e0da78f2 --- /dev/null +++ b/src/pkg/runtime/openbsd/386/rt0.s @@ -0,0 +1,6 @@ +// 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. + +TEXT _rt0_386_openbsd(SB),7,$0 + JMP _rt0_386(SB) diff --git a/src/pkg/runtime/openbsd/386/signal.c b/src/pkg/runtime/openbsd/386/signal.c new file mode 100644 index 0000000000..8b0d4ac616 --- /dev/null +++ b/src/pkg/runtime/openbsd/386/signal.c @@ -0,0 +1,189 @@ +// 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. + +#include "runtime.h" +#include "defs.h" +#include "signals.h" +#include "os.h" + +extern void runtime·sigtramp(void); + +typedef struct sigaction { + union { + void (*__sa_handler)(int32); + void (*__sa_sigaction)(int32, Siginfo*, void *); + } __sigaction_u; /* signal handler */ + uint32 sa_mask; /* signal mask to apply */ + int32 sa_flags; /* see signal options below */ +} Sigaction; + +void +runtime·dumpregs(Sigcontext *r) +{ + runtime·printf("eax %x\n", r->sc_eax); + runtime·printf("ebx %x\n", r->sc_ebx); + runtime·printf("ecx %x\n", r->sc_ecx); + runtime·printf("edx %x\n", r->sc_edx); + runtime·printf("edi %x\n", r->sc_edi); + runtime·printf("esi %x\n", r->sc_esi); + runtime·printf("ebp %x\n", r->sc_ebp); + runtime·printf("esp %x\n", r->sc_esp); + runtime·printf("eip %x\n", r->sc_eip); + runtime·printf("eflags %x\n", r->sc_eflags); + runtime·printf("cs %x\n", r->sc_cs); + runtime·printf("fs %x\n", r->sc_fs); + runtime·printf("gs %x\n", r->sc_gs); +} + +String +runtime·signame(int32 sig) +{ + if(sig < 0 || sig >= NSIG) + return runtime·emptystring; + return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name); +} + +void +runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) +{ + Sigcontext *r = context; + uintptr *sp; + + if(sig == SIGPROF) { + runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp); + return; + } + + if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) { + // Make it look like a call to the signal func. + // Have to pass arguments out of band since + // augmenting the stack frame would break + // the unwinding code. + gp->sig = sig; + gp->sigcode0 = info->si_code; + gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */ + gp->sigpc = r->sc_eip; + + // Only push runtime·sigpanic if r->sc_eip != 0. + // If r->sc_eip == 0, probably panicked because of a + // call to a nil func. Not pushing that onto sp will + // make the trace look like a call to runtime·sigpanic instead. + // (Otherwise the trace will end at runtime·sigpanic and we + // won't get to see who faulted.) + if(r->sc_eip != 0) { + sp = (uintptr*)r->sc_esp; + *--sp = r->sc_eip; + r->sc_esp = (uintptr)sp; + } + r->sc_eip = (uintptr)runtime·sigpanic; + return; + } + + if(runtime·sigtab[sig].flags & SigQueue) { + if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore)) + return; + runtime·exit(2); // SIGINT, SIGTERM, etc + } + + if(runtime·panicking) // traceback already printed + runtime·exit(2); + runtime·panicking = 1; + + if(sig < 0 || sig >= NSIG) + runtime·printf("Signal %d\n", sig); + else + runtime·printf("%s\n", runtime·sigtab[sig].name); + + runtime·printf("PC=%X\n", r->sc_eip); + runtime·printf("\n"); + + if(runtime·gotraceback()){ + runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp); + runtime·tracebackothers(gp); + runtime·dumpregs(r); + } + + runtime·exit(2); +} + +// Called from kernel on signal stack, so no stack split. +#pragma textflag 7 +void +runtime·sigignore(void) +{ +} + +void +runtime·signalstack(byte *p, int32 n) +{ + Sigaltstack st; + + st.ss_sp = (int8*)p; + st.ss_size = n; + st.ss_flags = 0; + runtime·sigaltstack(&st, nil); +} + +static void +sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart) +{ + Sigaction sa; + + runtime·memclr((byte*)&sa, sizeof sa); + sa.sa_flags = SA_SIGINFO|SA_ONSTACK; + if(restart) + sa.sa_flags |= SA_RESTART; + sa.sa_mask = ~0ULL; + if (fn == runtime·sighandler) + fn = (void*)runtime·sigtramp; + sa.__sigaction_u.__sa_sigaction = (void*)fn; + runtime·sigaction(i, &sa, nil); +} + +void +runtime·initsig(int32 queue) +{ + int32 i; + void *fn; + + runtime·siginit(); + + for(i = 0; iprofilehz = hz; +} + +void +os·sigpipe(void) +{ + sigaction(SIGPIPE, SIG_DFL, false); + runtime·raisesigpipe(); +} diff --git a/src/pkg/runtime/openbsd/386/sys.s b/src/pkg/runtime/openbsd/386/sys.s new file mode 100644 index 0000000000..d508ce1d49 --- /dev/null +++ b/src/pkg/runtime/openbsd/386/sys.s @@ -0,0 +1,254 @@ +// 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 386, OpenBSD +// /usr/src/sys/kern/syscalls.master for syscall numbers. +// + +#include "386/asm.h" + +// Exit the entire program (like C exit) +TEXT runtime·exit(SB),7,$-4 + MOVL $1, AX + INT $0x80 + CALL runtime·notok(SB) + RET + +TEXT runtime·exit1(SB),7,$-4 + MOVL $302, AX // sys_threxit + INT $0x80 + JAE 2(PC) + CALL runtime·notok(SB) + RET + +TEXT runtime·write(SB),7,$-4 + MOVL $4, AX // sys_write + INT $0x80 + RET + +TEXT runtime·raisesigpipe(SB),7,$12 + MOVL $299, AX // sys_getthrid + INT $80 + MOVL $0, 0(SP) + MOVL AX, 4(SP) // arg 1 - pid + MOVL $13, 8(SP) // arg 2 - signum == SIGPIPE + MOVL $37, AX // sys_kill + INT $0x80 + RET + +TEXT runtime·notok(SB),7,$0 + MOVL $0xf1, 0xf1 + RET + +TEXT runtime·mmap(SB),7,$36 + LEAL arg0+0(FP), SI + LEAL 4(SP), DI + CLD + MOVSL // arg 1 - addr + MOVSL // arg 2 - len + MOVSL // arg 3 - prot + MOVSL // arg 4 - flags + MOVSL // arg 5 - fd + MOVL $0, AX + STOSL // arg 6 - pad + MOVSL // arg 7 - offset + MOVL $0, AX // top 64 bits of file offset + STOSL + MOVL $197, AX // sys_mmap + INT $0x80 + JCC 2(PC) + NEGL AX + RET + +TEXT runtime·munmap(SB),7,$-4 + MOVL $73, AX // sys_munmap + INT $0x80 + JAE 2(PC) + CALL runtime·notok(SB) + RET + +TEXT runtime·setitimer(SB),7,$-4 + MOVL $83, AX + INT $0x80 + RET + +TEXT runtime·gettime(SB),7,$32 + MOVL $116, AX + LEAL 12(SP), BX + MOVL BX, 4(SP) + MOVL $0, 8(SP) + INT $0x80 + + MOVL 12(SP), BX // sec + MOVL sec+0(FP), DI + MOVL BX, (DI) + MOVL $0, 4(DI) // zero extend 32 -> 64 bits + + MOVL 16(SP), BX // usec + MOVL usec+4(FP), DI + MOVL BX, (DI) + RET + +TEXT runtime·sigaction(SB),7,$-4 + MOVL $46, AX // sys_sigaction + INT $0x80 + JAE 2(PC) + CALL runtime·notok(SB) + RET + +TEXT runtime·sigtramp(SB),7,$44 + get_tls(CX) + + // save g + MOVL g(CX), DI + MOVL DI, 20(SP) + + // g = m->gsignal + MOVL m(CX), BX + MOVL m_gsignal(BX), BX + MOVL BX, g(CX) + + // copy arguments for call to sighandler + MOVL signo+0(FP), BX + MOVL BX, 0(SP) + MOVL info+4(FP), BX + MOVL BX, 4(SP) + MOVL context+8(FP), BX + MOVL BX, 8(SP) + MOVL DI, 12(SP) + + CALL runtime·sighandler(SB) + + // restore g + get_tls(CX) + MOVL 20(SP), BX + MOVL BX, g(CX) + + // call sigreturn + MOVL context+8(FP), AX + MOVL $0, 0(SP) // syscall gap + MOVL AX, 4(SP) // arg 1 - sigcontext + MOVL $103, AX // sys_sigreturn + INT $0x80 + CALL runtime·notok(SB) + RET + +// int32 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void)); +TEXT runtime·rfork_thread(SB),7,$8 + MOVL flags+8(SP), AX + MOVL stack+12(SP), CX + + // Copy m, g, fn off parent stack for use by child. + SUBL $16, CX + MOVL mm+16(SP), SI + MOVL SI, 0(CX) + MOVL gg+20(SP), SI + MOVL SI, 4(CX) + MOVL fn+24(SP), SI + MOVL SI, 8(CX) + MOVL $1234, 12(CX) + MOVL CX, SI + + MOVL $0, 0(SP) // syscall gap + MOVL AX, 4(SP) // arg 1 - flags + MOVL $251, AX // sys_rfork + INT $0x80 + + // Return if rfork syscall failed + JCC 4(PC) + NEGL AX + MOVL AX, 48(SP) + RET + + // In parent, return. + CMPL AX, $0 + JEQ 3(PC) + MOVL AX, 48(SP) + RET + + // In child, on new stack. + MOVL SI, SP + + // Paranoia: check that SP is as we expect. + MOVL 12(SP), BP + CMPL BP, $1234 + JEQ 2(PC) + INT $3 + + // Reload registers + MOVL 0(SP), BX // m + MOVL 4(SP), DX // g + MOVL 8(SP), SI // fn + + // Initialize m->procid to thread ID + MOVL $299, AX // sys_getthrid + INT $0x80 + MOVL AX, m_procid(BX) + + // Set FS to point at m->tls + LEAL m_tls(BX), BP + PUSHAL // save registers + PUSHL BP + CALL runtime·settls(SB) + POPL AX + POPAL + + // Now segment is established. Initialize m, g. + get_tls(AX) + MOVL DX, g(AX) + MOVL BX, m(AX) + + CALL runtime·stackcheck(SB) // smashes AX, CX + MOVL 0(DX), DX // paranoia; check they are not nil + MOVL 0(BX), BX + + // more paranoia; check that stack splitting code works + PUSHAL + CALL runtime·emptyfunc(SB) + POPAL + + // Call fn + CALL SI + + CALL runtime·exit1(SB) + MOVL $0x1234, 0x1005 + RET + +TEXT runtime·sigaltstack(SB),7,$-8 + MOVL $288, AX // sys_sigaltstack + MOVL new+4(SP), BX + MOVL old+8(SP), CX + INT $0x80 + CMPL AX, $0xfffff001 + JLS 2(PC) + INT $3 + RET + +TEXT runtime·setldt(SB),7,$8 + // Under OpenBSD we set the GS base instead of messing with the LDT. + MOVL 16(SP), AX // tls0 + MOVL AX, 0(SP) + CALL runtime·settls(SB) + RET + +TEXT runtime·settls(SB),7,$16 + // adjust for ELF: wants to use -8(GS) and -4(GS) for g and m + MOVL 20(SP), CX + ADDL $8, CX + MOVL CX, 0(CX) + MOVL $0, 0(SP) // syscall gap + MOVL $9, 4(SP) // I386_SET_GSBASE (machine/sysarch.h) + MOVL CX, 8(SP) // pointer to base + MOVL $165, AX // sys_sysarch + INT $0x80 + JCC 2(PC) + CALL runtime·notok(SB) + RET + +TEXT runtime·osyield(SB),7,$-4 + MOVL $298, AX // sys_sched_yield + INT $0x80 + RET + +GLOBL runtime·tlsoffset(SB),$4 diff --git a/src/pkg/runtime/openbsd/defs.c b/src/pkg/runtime/openbsd/defs.c index d8adec9810..d0e0a19c35 100644 --- a/src/pkg/runtime/openbsd/defs.c +++ b/src/pkg/runtime/openbsd/defs.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -97,7 +96,8 @@ typedef stack_t $StackT; typedef struct timeval $Timeval; typedef struct itimerval $Itimerval; -// This is a hack to avoid pulling in machine/fpu.h and struct fxsave64. +// This is a hack to avoid pulling in machine/fpu.h. typedef void $sfxsave64; +typedef void $usavefpu; typedef struct sigcontext $Sigcontext; diff --git a/src/pkg/runtime/openbsd/mem.c b/src/pkg/runtime/openbsd/mem.c index 07abf2cfe0..46b6b07ee5 100644 --- a/src/pkg/runtime/openbsd/mem.c +++ b/src/pkg/runtime/openbsd/mem.c @@ -3,6 +3,11 @@ #include "os.h" #include "malloc.h" +enum +{ + ENOMEM = 12, +}; + void* runtime·SysAlloc(uintptr n) { @@ -33,19 +38,20 @@ runtime·SysFree(void *v, uintptr n) void* runtime·SysReserve(void *v, uintptr n) { + void *p; + // On 64-bit, people with ulimit -v set complain if we reserve too // much address space. Instead, assume that the reservation is okay // and check the assumption in SysMap. if(sizeof(void*) == 8) return v; - - return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); -} -enum -{ - ENOMEM = 12, -}; + p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); + if (p == ((void *)-ENOMEM)) + return nil; + else + return p; +} void runtime·SysMap(void *v, uintptr n)