diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
commit | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch) | |
tree | c0650497e988f47be9c6f2324fa692a52dea82e1 /src/pkg/runtime/linux/arm | |
parent | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff) | |
download | golang-upstream/60.tar.gz |
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/pkg/runtime/linux/arm')
-rw-r--r-- | src/pkg/runtime/linux/arm/defs.h | 149 | ||||
-rw-r--r-- | src/pkg/runtime/linux/arm/rt0.s | 6 | ||||
-rw-r--r-- | src/pkg/runtime/linux/arm/signal.c | 189 | ||||
-rw-r--r-- | src/pkg/runtime/linux/arm/sys.s | 319 |
4 files changed, 663 insertions, 0 deletions
diff --git a/src/pkg/runtime/linux/arm/defs.h b/src/pkg/runtime/linux/arm/defs.h new file mode 100644 index 000000000..09b558ed0 --- /dev/null +++ b/src/pkg/runtime/linux/arm/defs.h @@ -0,0 +1,149 @@ +// godefs -f-I/usr/src/linux-headers-2.6.26-2-versatile/include defs_arm.c + +// MACHINE GENERATED - DO NOT EDIT. + +// Constants +enum { + PROT_NONE = 0, + PROT_READ = 0x1, + PROT_WRITE = 0x2, + PROT_EXEC = 0x4, + MAP_ANON = 0x20, + MAP_PRIVATE = 0x2, + MAP_FIXED = 0x10, + SA_RESTART = 0x10000000, + SA_ONSTACK = 0x8000000, + SA_RESTORER = 0x4000000, + SA_SIGINFO = 0x4, + SIGHUP = 0x1, + SIGINT = 0x2, + SIGQUIT = 0x3, + SIGILL = 0x4, + SIGTRAP = 0x5, + SIGABRT = 0x6, + SIGBUS = 0x7, + SIGFPE = 0x8, + SIGKILL = 0x9, + SIGUSR1 = 0xa, + SIGSEGV = 0xb, + SIGUSR2 = 0xc, + SIGPIPE = 0xd, + SIGALRM = 0xe, + SIGSTKFLT = 0x10, + SIGCHLD = 0x11, + SIGCONT = 0x12, + SIGSTOP = 0x13, + SIGTSTP = 0x14, + SIGTTIN = 0x15, + SIGTTOU = 0x16, + SIGURG = 0x17, + SIGXCPU = 0x18, + SIGXFSZ = 0x19, + SIGVTALRM = 0x1a, + SIGPROF = 0x1b, + SIGWINCH = 0x1c, + SIGIO = 0x1d, + SIGPWR = 0x1e, + SIGSYS = 0x1f, + FPE_INTDIV = 0x1, + FPE_INTOVF = 0x2, + 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_PROF = 0x2, + ITIMER_VIRTUAL = 0x1, + O_RDONLY = 0, + O_CLOEXEC = 02000000, +}; + +// Types +#pragma pack on + +typedef uint32 Sigset; + +typedef struct Timespec Timespec; +struct Timespec { + int32 tv_sec; + int32 tv_nsec; +}; + +typedef struct Sigaltstack Sigaltstack; +struct Sigaltstack { + void *ss_sp; + int32 ss_flags; + uint32 ss_size; +}; + +typedef struct Sigcontext Sigcontext; +struct Sigcontext { + uint32 trap_no; + uint32 error_code; + uint32 oldmask; + uint32 arm_r0; + uint32 arm_r1; + uint32 arm_r2; + uint32 arm_r3; + uint32 arm_r4; + uint32 arm_r5; + uint32 arm_r6; + uint32 arm_r7; + uint32 arm_r8; + uint32 arm_r9; + uint32 arm_r10; + uint32 arm_fp; + uint32 arm_ip; + uint32 arm_sp; + uint32 arm_lr; + uint32 arm_pc; + uint32 arm_cpsr; + uint32 fault_address; +}; + +typedef struct Ucontext Ucontext; +struct Ucontext { + uint32 uc_flags; + Ucontext *uc_link; + Sigaltstack uc_stack; + Sigcontext uc_mcontext; + uint32 uc_sigmask; + int32 __unused[31]; + uint32 uc_regspace[128]; +}; + +typedef struct Timeval Timeval; +struct Timeval { + int32 tv_sec; + int32 tv_usec; +}; + +typedef struct Itimerval Itimerval; +struct Itimerval { + Timeval it_interval; + Timeval it_value; +}; + +typedef struct Siginfo Siginfo; +struct Siginfo { + int32 si_signo; + int32 si_errno; + int32 si_code; + uint8 _sifields[4]; +}; + +typedef struct Sigaction Sigaction; +struct Sigaction { + void *sa_handler; + uint32 sa_flags; + void *sa_restorer; + uint32 sa_mask; +}; +#pragma pack off diff --git a/src/pkg/runtime/linux/arm/rt0.s b/src/pkg/runtime/linux/arm/rt0.s new file mode 100644 index 000000000..8838b4891 --- /dev/null +++ b/src/pkg/runtime/linux/arm/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_arm_linux(SB),7,$0 + B _rt0_arm(SB) diff --git a/src/pkg/runtime/linux/arm/signal.c b/src/pkg/runtime/linux/arm/signal.c new file mode 100644 index 000000000..88a84d112 --- /dev/null +++ b/src/pkg/runtime/linux/arm/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" + +void +runtime·dumpregs(Sigcontext *r) +{ + runtime·printf("trap %x\n", r->trap_no); + runtime·printf("error %x\n", r->error_code); + runtime·printf("oldmask %x\n", r->oldmask); + runtime·printf("r0 %x\n", r->arm_r0); + runtime·printf("r1 %x\n", r->arm_r1); + runtime·printf("r2 %x\n", r->arm_r2); + runtime·printf("r3 %x\n", r->arm_r3); + runtime·printf("r4 %x\n", r->arm_r4); + runtime·printf("r5 %x\n", r->arm_r5); + runtime·printf("r6 %x\n", r->arm_r6); + runtime·printf("r7 %x\n", r->arm_r7); + runtime·printf("r8 %x\n", r->arm_r8); + runtime·printf("r9 %x\n", r->arm_r9); + runtime·printf("r10 %x\n", r->arm_r10); + runtime·printf("fp %x\n", r->arm_fp); + runtime·printf("ip %x\n", r->arm_ip); + runtime·printf("sp %x\n", r->arm_sp); + runtime·printf("lr %x\n", r->arm_lr); + runtime·printf("pc %x\n", r->arm_pc); + runtime·printf("cpsr %x\n", r->arm_cpsr); + runtime·printf("fault %x\n", r->fault_address); +} + +/* + * This assembler routine takes the args from registers, puts them on the stack, + * and calls sighandler(). + */ +extern void runtime·sigtramp(void); +extern void runtime·sigignore(void); // just returns +extern void runtime·sigreturn(void); // calls runtime·sigreturn + +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) +{ + Ucontext *uc; + Sigcontext *r; + + uc = context; + r = &uc->uc_mcontext; + + if(sig == SIGPROF) { + runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, 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 = r->fault_address; + gp->sigpc = r->arm_pc; + + // If this is a leaf function, we do smash LR, + // but we're not going back there anyway. + // Don't bother smashing if r->arm_pc is 0, + // which is probably a call to a nil func: the + // old link register is more useful in the stack trace. + if(r->arm_pc != 0) + r->arm_lr = r->arm_pc; + r->arm_pc = (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->arm_pc); + runtime·printf("\n"); + + if(runtime·gotraceback()){ + runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, 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 = 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_ONSTACK | SA_SIGINFO | SA_RESTORER; + if(restart) + sa.sa_flags |= SA_RESTART; + sa.sa_mask = ~0ULL; + sa.sa_restorer = (void*)runtime·sigreturn; + if(fn == runtime·sighandler) + fn = (void*)runtime·sigtramp; + sa.sa_handler = fn; + runtime·rt_sigaction(i, &sa, nil, 8); +} + +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/linux/arm/sys.s b/src/pkg/runtime/linux/arm/sys.s new file mode 100644 index 000000000..8619f0945 --- /dev/null +++ b/src/pkg/runtime/linux/arm/sys.s @@ -0,0 +1,319 @@ +// 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 arm, Linux +// + +#include "arm/asm.h" + +// OABI +//#define SYS_BASE 0x00900000 + +// EABI +#define SYS_BASE 0x0 + +#define SYS_exit (SYS_BASE + 1) +#define SYS_read (SYS_BASE + 3) +#define SYS_write (SYS_BASE + 4) +#define SYS_open (SYS_BASE + 5) +#define SYS_close (SYS_BASE + 6) +#define SYS_gettimeofday (SYS_BASE + 78) +#define SYS_clone (SYS_BASE + 120) +#define SYS_rt_sigreturn (SYS_BASE + 173) +#define SYS_rt_sigaction (SYS_BASE + 174) +#define SYS_sigaltstack (SYS_BASE + 186) +#define SYS_mmap2 (SYS_BASE + 192) +#define SYS_futex (SYS_BASE + 240) +#define SYS_exit_group (SYS_BASE + 248) +#define SYS_munmap (SYS_BASE + 91) +#define SYS_setitimer (SYS_BASE + 104) +#define SYS_mincore (SYS_BASE + 219) +#define SYS_gettid (SYS_BASE + 224) +#define SYS_tkill (SYS_BASE + 238) +#define SYS_sched_yield (SYS_BASE + 158) + +#define ARM_BASE (SYS_BASE + 0x0f0000) +#define SYS_ARM_cacheflush (ARM_BASE + 2) + +TEXT runtime·open(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW $SYS_open, R7 + SWI $0 + RET + +TEXT runtime·close(SB),7,$0 + MOVW 0(FP), R0 + MOVW $SYS_close, R7 + SWI $0 + RET + +TEXT runtime·write(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW $SYS_write, R7 + SWI $0 + RET + +TEXT runtime·read(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW $SYS_read, R7 + SWI $0 + RET + +TEXT runtime·exit(SB),7,$-4 + MOVW 0(FP), R0 + MOVW $SYS_exit_group, R7 + SWI $0 + MOVW $1234, R0 + MOVW $1002, R1 + MOVW R0, (R1) // fail hard + +TEXT runtime·exit1(SB),7,$-4 + MOVW 0(FP), R0 + MOVW $SYS_exit, R7 + SWI $0 + MOVW $1234, R0 + MOVW $1003, R1 + MOVW R0, (R1) // fail hard + +TEXT runtime·raisesigpipe(SB),7,$-4 + MOVW $SYS_gettid, R7 + SWI $0 + // arg 1 tid already in R0 from gettid + MOVW $13, R1 // arg 2 SIGPIPE + MOVW $SYS_tkill, R7 + SWI $0 + RET + +TEXT runtime·mmap(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW 12(FP), R3 + MOVW 16(FP), R4 + MOVW 20(FP), R5 + MOVW $SYS_mmap2, R7 + SWI $0 + RET + +TEXT runtime·munmap(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW $SYS_munmap, R7 + SWI $0 + RET + +TEXT runtime·setitimer(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW $SYS_setitimer, R7 + SWI $0 + RET + +TEXT runtime·mincore(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW $SYS_mincore, R7 + SWI $0 + RET + +TEXT runtime·gettime(SB),7,$32 + /* dummy version - return 0,0 */ + MOVW $0, R1 + MOVW 0(FP), R0 + MOVW R1, 0(R0) + MOVW R1, 4(R0) + MOVW 4(FP), R0 + MOVW R1, 0(R0) + +/* + attempt at real version - seg faults + + MOVW $8(SP), R0 + MOVW $0, R1 + MOVW $SYS_gettimeofday, R7 + SWI $0 + + MOVW 0(FP), R0 // sec + MOVW 8(SP), R1 + MOVW R1, 0(R0) + + MOVW 4(FP), R0 // usec + MOVW 12(SP), R1 + MOVW R1, 0(R0) +*/ + RET + +// int32 futex(int32 *uaddr, int32 op, int32 val, +// struct timespec *timeout, int32 *uaddr2, int32 val2); +TEXT runtime·futex(SB),7,$0 + MOVW 4(SP), R0 + MOVW 8(SP), R1 + MOVW 12(SP), R2 + MOVW 16(SP), R3 + MOVW 20(SP), R4 + MOVW 24(SP), R5 + MOVW $SYS_futex, R7 + SWI $0 + RET + + +// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void)); +TEXT runtime·clone(SB),7,$0 + MOVW flags+0(FP), R0 + MOVW stack+4(FP), R1 + MOVW $0, R2 // parent tid ptr + MOVW $0, R3 // tls_val + MOVW $0, R4 // child tid ptr + MOVW $0, R5 + + // Copy m, g, fn off parent stack for use by child. + // TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying + MOVW $-16(R1), R1 + MOVW mm+8(FP), R6 + MOVW R6, 0(R1) + MOVW gg+12(FP), R6 + MOVW R6, 4(R1) + MOVW fn+16(FP), R6 + MOVW R6, 8(R1) + MOVW $1234, R6 + MOVW R6, 12(R1) + + MOVW $SYS_clone, R7 + SWI $0 + + // In parent, return. + CMP $0, R0 + BEQ 2(PC) + RET + + // Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup' + MOVW 12(R13), R0 + MOVW $1234, R1 + CMP R0, R1 + BEQ 2(PC) + BL runtime·abort(SB) + + MOVW 0(R13), m + MOVW 4(R13), g + + // paranoia; check they are not nil + MOVW 0(m), R0 + MOVW 0(g), R0 + + BL runtime·emptyfunc(SB) // fault if stack check is wrong + + // Initialize m->procid to Linux tid + MOVW $SYS_gettid, R7 + SWI $0 + MOVW R0, m_procid(m) + + // Call fn + MOVW 8(R13), R0 + MOVW $16(R13), R13 + BL (R0) + + MOVW $0, R0 + MOVW R0, 4(R13) + BL runtime·exit1(SB) + + // It shouldn't return + MOVW $1234, R0 + MOVW $1005, R1 + MOVW R0, (R1) + + +TEXT runtime·cacheflush(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW $0, R2 + MOVW $SYS_ARM_cacheflush, R7 + SWI $0 + RET + +TEXT runtime·sigaltstack(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW $SYS_sigaltstack, R7 + SWI $0 + RET + +TEXT runtime·sigignore(SB),7,$0 + RET + +TEXT runtime·sigtramp(SB),7,$24 + // save g + MOVW g, R3 + MOVW g, 20(R13) + + // g = m->gsignal + MOVW m_gsignal(m), g + + // copy arguments for call to sighandler + MOVW R0, 4(R13) + MOVW R1, 8(R13) + MOVW R2, 12(R13) + MOVW R3, 16(R13) + + BL runtime·sighandler(SB) + + // restore g + MOVW 20(R13), g + + RET + +TEXT runtime·rt_sigaction(SB),7,$0 + MOVW 0(FP), R0 + MOVW 4(FP), R1 + MOVW 8(FP), R2 + MOVW 12(FP), R3 + MOVW $SYS_rt_sigaction, R7 + SWI $0 + RET + +TEXT runtime·sigreturn(SB),7,$0 + MOVW $SYS_rt_sigreturn, R7 + SWI $0 + RET + +// Use kernel version instead of native armcas in ../../arm.s. +// See ../../../sync/atomic/asm_linux_arm.s for details. +TEXT cas<>(SB),7,$0 + MOVW $0xffff0fc0, PC + +TEXT runtime·cas(SB),7,$0 + MOVW valptr+0(FP), R2 + MOVW old+4(FP), R0 +casagain: + MOVW new+8(FP), R1 + BL cas<>(SB) + BCC cascheck + MOVW $1, R0 + RET +cascheck: + // Kernel lies; double-check. + MOVW valptr+0(FP), R2 + MOVW old+4(FP), R0 + MOVW 0(R2), R3 + CMP R0, R3 + BEQ casagain + MOVW $0, R0 + RET + + +TEXT runtime·casp(SB),7,$0 + B runtime·cas(SB) + +TEXT runtime·osyield(SB),7,$0 + MOVW $SYS_sched_yield, R7 + SWI $0 + RET |