]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: FreeBSD/ARM support
authorShenghou Ma <minux.ma@gmail.com>
Fri, 12 Oct 2012 15:19:39 +0000 (23:19 +0800)
committerShenghou Ma <minux.ma@gmail.com>
Fri, 12 Oct 2012 15:19:39 +0000 (23:19 +0800)
R=rsc
CC=golang-dev
https://golang.org/cl/6625071

src/pkg/runtime/defs_freebsd_arm.h [new file with mode: 0644]
src/pkg/runtime/rt0_freebsd_arm.s [new file with mode: 0644]
src/pkg/runtime/signal_freebsd_arm.c [new file with mode: 0644]
src/pkg/runtime/sys_freebsd_arm.s [new file with mode: 0644]

diff --git a/src/pkg/runtime/defs_freebsd_arm.h b/src/pkg/runtime/defs_freebsd_arm.h
new file mode 100644 (file)
index 0000000..351259e
--- /dev/null
@@ -0,0 +1,183 @@
+// godefs -f -m32 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,
+       MAP_FIXED = 0x10,
+       SA_SIGINFO = 0x40,
+       SA_RESTART = 0x2,
+       SA_ONSTACK = 0x1,
+       UMTX_OP_WAIT = 0x2,
+       UMTX_OP_WAKE = 0x3,
+       EINTR = 0x4,
+       SIGHUP = 0x1,
+       SIGINT = 0x2,
+       SIGQUIT = 0x3,
+       SIGILL = 0x4,
+       SIGTRAP = 0x5,
+       SIGABRT = 0x6,
+       SIGEMT = 0x7,
+       SIGFPE = 0x8,
+       SIGKILL = 0x9,
+       SIGBUS = 0xa,
+       SIGSEGV = 0xb,
+       SIGSYS = 0xc,
+       SIGPIPE = 0xd,
+       SIGALRM = 0xe,
+       SIGTERM = 0xf,
+       SIGURG = 0x10,
+       SIGSTOP = 0x11,
+       SIGTSTP = 0x12,
+       SIGCONT = 0x13,
+       SIGCHLD = 0x14,
+       SIGTTIN = 0x15,
+       SIGTTOU = 0x16,
+       SIGIO = 0x17,
+       SIGXCPU = 0x18,
+       SIGXFSZ = 0x19,
+       SIGVTALRM = 0x1a,
+       SIGPROF = 0x1b,
+       SIGWINCH = 0x1c,
+       SIGINFO = 0x1d,
+       SIGUSR1 = 0x1e,
+       SIGUSR2 = 0x1f,
+       FPE_INTDIV = 0x2,
+       FPE_INTOVF = 0x1,
+       FPE_FLTDIV = 0x3,
+       FPE_FLTOVF = 0x4,
+       FPE_FLTUND = 0x5,
+       FPE_FLTRES = 0x6,
+       FPE_FLTINV = 0x7,
+       FPE_FLTSUB = 0x8,
+       BUS_ADRALN = 0x1,
+       BUS_ADRERR = 0x2,
+       BUS_OBJERR = 0x3,
+       SEGV_MAPERR = 0x1,
+       SEGV_ACCERR = 0x2,
+       ITIMER_REAL = 0,
+       ITIMER_VIRTUAL = 0x1,
+       ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Rtprio Rtprio;
+struct Rtprio {
+       uint16 type;
+       uint16 prio;
+};
+
+typedef struct ThrParam ThrParam;
+struct ThrParam {
+       void *start_func;
+       void *arg;
+       int8 *stack_base;
+       uint32 stack_size;
+       int8 *tls_base;
+       uint32 tls_size;
+       int32 *child_tid;
+       int32 *parent_tid;
+       int32 flags;
+       Rtprio *rtp;
+       void* spare[3];
+};
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+       int8 *ss_sp;
+       uint32 ss_size;
+       int32 ss_flags;
+};
+
+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;
+       uint32 ss_size;
+       int32 ss_flags;
+};
+
+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[32];
+};
+
+typedef struct Mcontext Mcontext;
+struct Mcontext {
+       uint32 r0;
+       uint32 r1;
+       uint32 r2;
+       uint32 r3;
+       uint32 r4;
+       uint32 r5;
+       uint32 r6;
+       uint32 r7;
+       uint32 r8;
+       uint32 r9;
+       uint32 r10;
+       uint32 r11;
+       uint32 r12;
+       uint32 r13;
+       uint32 r14;
+       uint32 r15;
+       uint32 cpsr;
+       uint32 _pad[1+33+1]; // union __fpu
+};
+
+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 pad_godefs_0[12];
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+       int64 tv_sec; // FreeBSD/ARM uses int64 for time_t
+       int32 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+       int64 tv_sec; // FreeBSD/ARM uses int64 for time_t
+       int32 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+       Timeval it_interval;
+       Timeval it_value;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/rt0_freebsd_arm.s b/src/pkg/runtime/rt0_freebsd_arm.s
new file mode 100644 (file)
index 0000000..085fccf
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2012 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.
+
+// FreeBSD and Linux use the same linkage to main
+
+TEXT _rt0_arm_freebsd(SB),7,$-4
+       B       _rt0_arm(SB)
diff --git a/src/pkg/runtime/signal_freebsd_arm.c b/src/pkg/runtime/signal_freebsd_arm.c
new file mode 100644 (file)
index 0000000..c9fe7fe
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright 2012 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_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Mcontext *r)
+{
+       runtime·printf("r0      %x\n", r->r0);
+       runtime·printf("r1      %x\n", r->r1);
+       runtime·printf("r2      %x\n", r->r2);
+       runtime·printf("r3      %x\n", r->r3);
+       runtime·printf("r4      %x\n", r->r4);
+       runtime·printf("r5      %x\n", r->r5);
+       runtime·printf("r6      %x\n", r->r6);
+       runtime·printf("r7      %x\n", r->r7);
+       runtime·printf("r8      %x\n", r->r8);
+       runtime·printf("r9      %x\n", r->r9);
+       runtime·printf("r10     %x\n", r->r10);
+       runtime·printf("fp      %x\n", r->r11);
+       runtime·printf("ip      %x\n", r->r12);
+       runtime·printf("sp      %x\n", r->r13);
+       runtime·printf("lr      %x\n", r->r14);
+       runtime·printf("pc      %x\n", r->r15);
+       runtime·printf("cpsr    %x\n", r->cpsr);
+}
+
+extern void runtime·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
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+       Ucontext *uc;
+       Mcontext *r;
+       SigTab *t;
+
+       uc = context;
+       r = &uc->uc_mcontext;
+
+       if(sig == SIGPROF) {
+               runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
+               return;
+       }
+
+       t = &runtime·sigtab[sig];
+       if(info->si_code != SI_USER && (t->flags & SigPanic)) {
+               if(gp == nil)
+                       goto Throw;
+               // 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)info->si_addr;
+               gp->sigpc = r->r15;
+
+               // Only push runtime·sigpanic if r->mc_rip != 0.
+               // If r->mc_rip == 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->r15 != 0)
+                       r->r14 = r->r15;
+               // In case we are panicking from external C code
+               r->r10 = (uintptr)gp;
+               r->r9 = (uintptr)m;
+               r->r15 = (uintptr)runtime·sigpanic;
+               return;
+       }
+
+       if(info->si_code == SI_USER || (t->flags & SigNotify))
+               if(runtime·sigsend(sig))
+                       return;
+       if(t->flags & SigKill)
+               runtime·exit(2);
+       if(!(t->flags & SigThrow))
+               return;
+
+Throw:
+       runtime·startpanic();
+
+       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->r15);
+       runtime·printf("\n");
+
+       if(runtime·gotraceback()){
+               runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
+               runtime·tracebackothers(gp);
+               runtime·printf("\n");
+               runtime·dumpregs(r);
+       }
+
+//     breakpoint();
+       runtime·exit(2);
+}
+
+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);
+}
+
+void
+runtime·setsig(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·checkgoarm(void)
+{
+       // TODO(minux)
+}
+
+#pragma textflag 7
+int64
+runtime·cputicks() {
+       // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+       // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+       // TODO: need more entropy to better seed fastrand1.
+       return runtime·nanotime();
+}
diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/pkg/runtime/sys_freebsd_arm.s
new file mode 100644 (file)
index 0000000..097fcd0
--- /dev/null
@@ -0,0 +1,262 @@
+// Copyright 2012 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 ARM, FreeBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+       
+TEXT runtime·sys_umtx_op(SB),7,$0
+       MOVW 0(FP), R0
+       MOVW 4(FP), R1
+       MOVW 8(FP), R2
+       MOVW 12(FP), R3
+       ADD $20, R13 // arg 5 is passed on stack
+       SWI $454
+       SUB $20, R13
+       // BCS error
+       RET
+
+TEXT runtime·thr_new(SB),7,$0
+       MOVW 0(FP), R0
+       MOVW 4(FP), R1
+       SWI $455
+       RET
+
+TEXT runtime·thr_start(SB),7,$0
+       MOVW R0, R9 // m
+
+       // TODO(minux): set up TLS?
+
+       // set up g
+       MOVW m_g0(R9), R10
+       BL runtime·emptyfunc(SB) // fault if stack check is wrong
+       BL runtime·mstart(SB)
+       MOVW $2, R9  // crash (not reached)
+       MOVW R9, (R9)
+       RET
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-8
+       MOVW 0(FP), R0  // arg 1 exit status
+       SWI $1
+       MOVW.CS $0, R9 // crash on syscall failure
+       MOVW.CS R9, (R9)
+       RET
+
+TEXT runtime·exit1(SB),7,$-8
+       MOVW 0(FP), R0  // arg 1 exit status
+       SWI $431
+       MOVW.CS $0, R9 // crash on syscall failure
+       MOVW.CS R9, (R9)
+       RET
+
+TEXT runtime·write(SB),7,$-8
+       MOVW 0(FP), R0  // arg 1 fd
+       MOVW 4(FP), R1  // arg 2 buf
+       MOVW 8(FP), R2  // arg 3 count
+       SWI $4
+       RET
+
+TEXT runtime·getrlimit(SB),7,$-8
+       MOVW 0(FP), R0
+       MOVW 4(FP), R1
+       MOVW 8(FP), R2
+       SWI $194
+       RET
+
+TEXT runtime·raisesigpipe(SB),7,$8
+       // thr_self(&4(R13))
+       MOVW $4(R13), R0 // arg 1 &4(R13)
+       SWI $432
+       // thr_kill(self, SIGPIPE)
+       MOVW 4(R13), R0 // arg 1 id
+       MOVW $13, R1    // arg 2 SIGPIPE
+       SWI $433
+       RET
+
+TEXT runtime·setitimer(SB), 7, $-8
+       MOVW 0(FP), R0
+       MOVW 4(FP), R1
+       MOVW 8(FP), R2
+       SWI $83
+       RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+       MOVW $8(R13), R0
+       MOVW $0, R1
+       SWI $116 // gettimeofday
+
+       MOVW 8(R13), R0 // sec.low
+       MOVW 16(R13), R2 // usec
+
+       MOVW R0, 0(FP)
+       MOVW $0, R1
+       MOVW R1, 4(FP)
+       MOVW $1000, R3
+       MUL R3, R2
+       MOVW R2, 8(FP)
+       RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
+       MOVW $8(R13), R0
+       MOVW $0, R1
+       SWI $116 // gettimeofday
+
+       MOVW 8(R13), R0 // sec.low
+       MOVW 16(R13), R2 // usec
+
+       MOVW $1000000000, R3
+       MULLU R0, R3, (R1, R0)
+       MOVW $1000, R3
+       MOVW $0, R4
+       MUL R3, R2
+       ADD.S R2, R0
+       ADC R4, R1
+       
+       MOVW 0(FP), R3
+       MOVW R0, 0(R3)
+       MOVW R1, 4(R3)
+       RET
+
+TEXT runtime·sigaction(SB),7,$-8
+       MOVW 0(FP), R0          // arg 1 sig
+       MOVW 4(FP), R1          // arg 2 act
+       MOVW 8(FP), R2          // arg 3 oact
+       SWI $416
+       MOVW.CS $0, R9 // crash on syscall failure
+       MOVW.CS R9, (R9)
+       RET
+
+TEXT runtime·sigtramp(SB),7,$24
+       // this might be called in external code context,
+       // where g and m are not set.
+       // first save R0, because cgo_load_gm will clobber it
+       // TODO(adonovan): call runtime·badsignal if m=0, like other platforms?
+       MOVW    R0, 4(R13) // signum
+       MOVW    cgo_load_gm(SB), R0
+       CMP     $0, R0
+       BL.NE   (R0)
+
+       // save g
+       MOVW R10, R4
+       MOVW R10, 20(R13)
+
+       // g = m->signal
+       MOVW m_gsignal(R9), R10
+
+       // R0 is already saved
+       MOVW R1, 8(R13) // info
+       MOVW R2, 12(R13) // context
+       MOVW R4, 16(R13) // oldg
+
+       BL runtime·sighandler(SB)
+
+       // restore g
+       MOVW 20(R13), R10
+       RET
+
+TEXT runtime·mmap(SB),7,$12
+       MOVW 0(FP), R0          // arg 1 addr
+       MOVW 4(FP), R1          // arg 2 len
+       MOVW 8(FP), R2          // arg 3 prot
+       MOVW 12(FP), R3         // arg 4 flags
+       // arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
+       // note the C runtime only passes the 32-bit offset_lo to us
+       MOVW 16(FP), R4         // arg 5
+       MOVW R4, 4(R13)
+       MOVW 20(FP), R5         // arg 6 lower 32-bit
+       MOVW R5, 8(R13)
+       MOVW $0, R6 // higher 32-bit for arg 6
+       MOVW R6, 12(R13)
+       ADD $4, R13 // pass arg 5 and arg 6 on stack
+       SWI $477
+       SUB $4, R13
+       RET
+
+TEXT runtime·munmap(SB),7,$0
+       MOVW 0(FP), R0          // arg 1 addr
+       MOVW 4(FP), R1          // arg 2 len
+       SWI $73
+       MOVW.CS $0, R9 // crash on syscall failure
+       MOVW.CS R9, (R9)
+       RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+       MOVW new+0(FP), R0
+       MOVW old+4(FP), R1
+       SWI $53
+       MOVW.CS $0, R9 // crash on syscall failure
+       MOVW.CS R9, (R9)
+       RET
+
+TEXT runtime·usleep(SB),7,$16
+       MOVW usec+0(FP), R0
+       MOVW R0, R2
+       MOVW $1000000, R1
+       DIV R1, R0
+       // 0(R13) is the saved LR, don't use it
+       MOVW R0, 4(R13) // tv_sec.low
+       MOVW $0, R0
+       MOVW R0, 8(R13) // tv_sec.high
+       MOD R1, R2
+       MOVW $1000, R1
+       MUL R1, R2
+       MOVW R2, 12(R13) // tv_nsec
+
+       MOVW $4(R13), R0 // arg 1 - rqtp
+       MOVW $0, R1      // arg 2 - rmtp
+       SWI $240 // sys_nanosleep
+       RET
+
+TEXT runtime·sysctl(SB),7,$0
+       MOVW 0(FP), R0  // arg 1 - name
+       MOVW 4(FP), R1  // arg 2 - namelen
+       MOVW 8(FP), R2  // arg 3 - oldp
+       MOVW 12(FP), R3 // arg 4 - oldlenp
+       // arg 5 (newp) and arg 6 (newlen) are passed on stack
+       ADD $20, R13
+       SWI $202 // sys___sysctl
+       SUB.CS $0, R0, R0
+       SUB $20, R13
+       RET
+
+TEXT runtime·osyield(SB),7,$-4
+       SWI $331        // sys_sched_yield
+       RET
+
+TEXT runtime·sigprocmask(SB),7,$0
+       MOVW $3, R0     // arg 1 - how (SIG_SETMASK)
+       MOVW 0(FP), R1  // arg 2 - set
+       MOVW 4(FP), R2  // arg 3 - oset
+       SWI $340        // sys_sigprocmask
+       MOVW.CS $0, R9 // crash on syscall failure
+       MOVW.CS R9, (R9)
+       RET
+
+TEXT runtime·cacheflush(SB),7,$0
+       MOVW $0, R0 // icacheflush
+       MOVW 0(FP), R1 // start
+       MOVW 4(FP), R2 // end
+       SUB R1, R2 // R2 = length
+       SWI $165 // sysarch
+       RET
+
+TEXT runtime·casp(SB),7,$0
+       B       runtime·cas(SB)
+
+// TODO(minux): this is only valid for ARMv6+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//     if(*val == old){
+//             *val = new;
+//             return 1;
+//     }else
+//             return 0;
+TEXT runtime·cas(SB),7,$0
+       B runtime·armcas(SB)