]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add runtime support for openbsd 386
authorJoel Sing <jsing@google.com>
Mon, 29 Aug 2011 14:42:16 +0000 (10:42 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 29 Aug 2011 14:42:16 +0000 (10:42 -0400)
Add openbsd 386 runtime support, partially based on the existing
freebsd 386 runtime.

This requires change 4973043.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4951043

src/pkg/runtime/openbsd/386/rt0.s [new file with mode: 0644]
src/pkg/runtime/openbsd/386/signal.c [new file with mode: 0644]
src/pkg/runtime/openbsd/386/sys.s [new file with mode: 0644]
src/pkg/runtime/openbsd/defs.c
src/pkg/runtime/openbsd/mem.c

diff --git a/src/pkg/runtime/openbsd/386/rt0.s b/src/pkg/runtime/openbsd/386/rt0.s
new file mode 100644 (file)
index 0000000..e7e0da7
--- /dev/null
@@ -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 (file)
index 0000000..8b0d4ac
--- /dev/null
@@ -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; i<NSIG; i++) {
+               if(runtime·sigtab[i].flags) {
+                       if((runtime·sigtab[i].flags & SigQueue) != queue)
+                               continue;
+                       if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+                               fn = runtime·sighandler;
+                       else
+                               fn = runtime·sigignore;
+                       sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+               }
+       }
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+       Itimerval it;
+       
+       runtime·memclr((byte*)&it, sizeof it);
+       if(hz == 0) {
+               runtime·setitimer(ITIMER_PROF, &it, nil);
+               sigaction(SIGPROF, SIG_IGN, true);
+       } else {
+               sigaction(SIGPROF, runtime·sighandler, true);
+               it.it_interval.tv_sec = 0;
+               it.it_interval.tv_usec = 1000000 / hz;
+               it.it_value = it.it_interval;
+               runtime·setitimer(ITIMER_PROF, &it, nil);
+       }
+       m->profilehz = 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 (file)
index 0000000..d508ce1
--- /dev/null
@@ -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
index d8adec9810b97b68c80c25db346834ff78fb6874..d0e0a19c357479b5f2b12a8527a198ae52117c72 100644 (file)
@@ -14,7 +14,6 @@
 #include <sys/time.h>
 #include <sys/unistd.h>
 #include <sys/signal.h>
-#include <machine/mcontext.h>
 #include <errno.h>
 #include <signal.h>
 
@@ -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;
index 07abf2cfe0556d0fac643922cc7d8a7a90216a53..46b6b07ee5b95413994c42037a194add098e5e1c 100644 (file)
@@ -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)