From 8522a478bb5b85dd78c361f104b82326cd71ee1b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 17 Jun 2009 15:15:55 -0700 Subject: [PATCH] update 386 to new runtime (CL 30381) R=r DELTA=298 (119 added, 81 deleted, 98 changed) OCL=30427 CL=30443 --- src/cmd/8l/obj.c | 2 +- src/cmd/8l/pass.c | 20 +--- src/pkg/runtime/386/asm.s | 159 +++++++++++++++++++------------ src/pkg/runtime/386/traceback.c | 21 ++-- src/pkg/runtime/darwin/386/sys.s | 23 +++-- src/pkg/runtime/darwin/thread.c | 6 +- src/pkg/runtime/linux/386/sys.s | 126 +++++++++++++----------- src/pkg/runtime/linux/os.h | 4 +- src/pkg/runtime/linux/thread.c | 19 ++-- 9 files changed, 209 insertions(+), 171 deletions(-) diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index c3d4b9f659b..ef4e9a9b902 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -1038,7 +1038,7 @@ loop: s = p->from.sym; if(s != S && s->dupok) { if(debug['v']) - Bprint(&bso, "skipping %s in %s: dupok", s->name, pn); + Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); goto loop; } if(s != S) { diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index feaf287674d..fa6d6a00fe1 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -30,7 +30,7 @@ #include "l.h" -// see ../../runtime/proc.c:/StackGuard +// see ../../pkg/runtime/proc.c:/StackGuard enum { StackSmall = 128, @@ -619,29 +619,17 @@ dostkoff(void) q = p; } - p = appendp(p); // load m into DX + p = appendp(p); // save frame size in DX p->as = AMOVL; - p->from.type = D_INDIR+D_FS; - p->from.offset = 4; p->to.type = D_DX; - if(q1) { - q1->pcond = p; - q1 = P; - } - - p = appendp(p); // save autoffset in 4(DX) - p->as = AMOVL; - p->to.type = D_INDIR+D_DX; - p->to.offset = 4; /* 160 comes from 3 calls (3*8) 4 safes (4*8) and 104 guard */ p->from.type = D_CONST; if(autoffset+160 > 4096) p->from.offset = (autoffset+160) & ~7LL; - p = appendp(p); // save textarg in 8(DX) + p = appendp(p); // save arg size in AX p->as = AMOVL; - p->to.type = D_INDIR+D_DX; - p->to.offset = 8; + p->to.type = D_AX; p->from.type = D_CONST; p->from.offset = curtext->to.offset2; diff --git a/src/pkg/runtime/386/asm.s b/src/pkg/runtime/386/asm.s index 5d3c4261ab2..7b59bc7e31d 100644 --- a/src/pkg/runtime/386/asm.s +++ b/src/pkg/runtime/386/asm.s @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include "386/asm.h" + TEXT _rt0_386(SB),7,$0 // copy arguments forward on an even stack MOVL 0(SP), AX // argc @@ -11,17 +13,6 @@ TEXT _rt0_386(SB),7,$0 MOVL AX, 120(SP) // save argc, argv away MOVL BX, 124(SP) -/* - // write "go386\n" - PUSHL $6 - PUSHL $hello(SB) - PUSHL $1 - CALL sys·write(SB) - POPL AX - POPL AX - POPL AX -*/ - CALL ldt0setup(SB) // set up %fs to refer to that ldt entry @@ -37,19 +28,18 @@ TEXT _rt0_386(SB),7,$0 ok: // set up m and g "registers" - // g is 0(FS), m is 4(FS) LEAL g0(SB), CX - MOVL CX, 0(FS) + MOVL CX, g LEAL m0(SB), AX - MOVL AX, 4(FS) + MOVL AX, m // save m->g0 = g0 - MOVL CX, 0(AX) + MOVL CX, m_g0(AX) // create istack out of the OS stack LEAL (-8192+104)(SP), AX // TODO: 104? - MOVL AX, 0(CX) // 8(g) is stack limit (w 104b guard) - MOVL SP, 4(CX) // 12(g) is base + MOVL AX, g_stackguard(CX) + MOVL SP, g_stackbase(CX) CALL emptyfunc(SB) // fault if stack check is wrong // convention is D is always cleared @@ -68,7 +58,7 @@ ok: // create a new goroutine to start program PUSHL $mainstart(SB) // entry - PUSHL $8 // arg size + PUSHL $0 // arg size CALL sys·newproc(SB) POPL AX POPL AX @@ -93,51 +83,105 @@ TEXT breakpoint(SB),7,$0 BYTE $0xcc RET -// go-routine -TEXT gogo(SB), 7, $0 - MOVL 4(SP), AX // gobuf - MOVL 0(AX), SP // restore SP - MOVL 4(AX), AX - MOVL AX, 0(SP) // put PC on the stack - MOVL $1, AX - RET +/* + * go-routine + */ +// uintptr gosave(Gobuf*) +// save state in Gobuf; setjmp TEXT gosave(SB), 7, $0 - MOVL 4(SP), AX // gobuf - MOVL SP, 0(AX) // save SP - MOVL 0(SP), BX - MOVL BX, 4(AX) // save PC - MOVL $0, AX // return 0 + MOVL 4(SP), AX // gobuf + LEAL 4(SP), BX // caller's SP + MOVL BX, gobuf_sp(AX) + MOVL 0(SP), BX // caller's PC + MOVL BX, gobuf_pc(AX) + MOVL g, BX + MOVL BX, gobuf_g(AX) + MOVL $0, AX // return 0 RET -// support for morestack - -// return point when leaving new stack. -// save AX, jmp to lesstack to switch back -TEXT retfromnewstack(SB),7,$0 - MOVL 4(FS), BX // m - MOVL AX, 12(BX) // save AX in m->cret - JMP lessstack(SB) - -// gogo, returning 2nd arg instead of 1 -TEXT gogoret(SB), 7, $0 - MOVL 8(SP), AX // return 2nd arg - MOVL 4(SP), BX // gobuf - MOVL 0(BX), SP // restore SP - MOVL 4(BX), BX - MOVL BX, 0(SP) // put PC on the stack - RET - -TEXT setspgoto(SB), 7, $0 - MOVL 4(SP), AX // SP - MOVL 8(SP), BX // fn to call - MOVL 12(SP), CX // fn to return - MOVL AX, SP - PUSHL CX +// void gogo(Gobuf*, uintptr) +// restore state from Gobuf; longjmp +TEXT gogo(SB), 7, $0 + MOVL 8(SP), AX // return 2nd arg + MOVL 4(SP), BX // gobuf + MOVL gobuf_g(BX), DX + MOVL 0(DX), CX // make sure g != nil + MOVL DX, g + MOVL gobuf_sp(BX), SP // restore SP + MOVL gobuf_pc(BX), BX JMP BX - POPL AX // not reached + +// void gogocall(Gobuf*, void (*fn)(void)) +// restore state from Gobuf but then call fn. +// (call fn, returning to state in Gobuf) +TEXT gogocall(SB), 7, $0 + MOVL 8(SP), AX // fn + MOVL 4(SP), BX // gobuf + MOVL gobuf_g(BX), DX + MOVL DX, g + MOVL 0(DX), CX // make sure g != nil + MOVL gobuf_sp(BX), SP // restore SP + MOVL gobuf_pc(BX), BX + PUSHL BX + JMP AX + POPL BX // not reached + +/* + * support for morestack + */ + +// Called during function prolog when more stack is needed. +TEXT sys·morestack(SB),7,$0 + // Cannot grow scheduler stack (m->g0). + MOVL m, BX + MOVL m_g0(BX), SI + CMPL g, SI + JNE 2(PC) + INT $3 + + // frame size in DX + // arg size in AX + // Save in m. + MOVL DX, m_moreframe(BX) + MOVL AX, m_moreargs(BX) + + // Called from f. + // Set m->morebuf to f's caller. + MOVL 4(SP), DI // f's caller's PC + MOVL DI, (m_morebuf+gobuf_pc)(BX) + LEAL 8(SP), CX // f's caller's SP + MOVL CX, (m_morebuf+gobuf_sp)(BX) + MOVL g, SI + MOVL SI, (m_morebuf+gobuf_g)(BX) + + // Set m->morepc to f's PC. + MOVL 0(SP), AX + MOVL AX, m_morepc(BX) + + // Call newstack on m's scheduling stack. + MOVL m_g0(BX), BP + MOVL BP, g + MOVL (m_sched+gobuf_sp)(BX), SP + CALL newstack(SB) + MOVL $0, 0x1003 // crash if newstack returns RET +// Return point when leaving stack. +TEXT sys·lessstack(SB), 7, $0 + // Save return value in m->cret + MOVL m, BX + MOVL AX, m_cret(BX) + + // Call oldstack on m's scheduling stack. + MOVL m_g0(BX), DX + MOVL DX, g + MOVL (m_sched+gobuf_sp)(BX), SP + CALL oldstack(SB) + MOVL $0, 0x1004 // crash if oldstack returns + RET + + // bool cas(int32 *val, int32 old, int32 new) // Atomically: // if(*val == old){ @@ -212,6 +256,3 @@ TEXT emptyfunc(SB),0,$0 TEXT abort(SB),7,$0 INT $0x3 -DATA hello+0(SB)/8, $"go386\n\z\z" -GLOBL hello+0(SB), $8 - diff --git a/src/pkg/runtime/386/traceback.c b/src/pkg/runtime/386/traceback.c index 05724d9ac91..22a1bee5d7d 100644 --- a/src/pkg/runtime/386/traceback.c +++ b/src/pkg/runtime/386/traceback.c @@ -27,19 +27,19 @@ traceback(byte *pc0, byte *sp, G *g) stk = (Stktop*)g->stackbase; for(n=0; n<100; n++) { - while(pc == (uintptr)retfromnewstack) { + if(pc == (uint64)sys·lessstack) { + // printf("--\n"); // pop to earlier stack block - sp = stk->oldsp; - stk = (Stktop*)stk->oldbase; - pc = *(uintptr*)(sp+sizeof(uintptr)); - sp += 2*sizeof(uintptr); // two irrelevant calls on stack: morestack plus its call + pc = (uintptr)stk->gobuf.pc; + sp = stk->gobuf.sp; + stk = (Stktop*)stk->stackbase; } f = findfunc(pc); if(f == nil) { // dangerous, but poke around to see if it is a closure p = (byte*)pc; // ADDL $xxx, SP; RET - if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) { + if(p != 0 && p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) { sp += *(uint32*)(p+2) + 8; pc = *(uintptr*)(sp - 8); if(pc <= 0x1000) @@ -109,11 +109,10 @@ runtime·Caller(int32 n, uintptr retpc, String retfile, int32 retline, bool retb // now unwind n levels stk = (Stktop*)g->stackbase; while(n-- > 0) { - while(pc == (uintptr)retfromnewstack) { - sp = stk->oldsp; - stk = (Stktop*)stk->oldbase; - pc = *((uintptr*)sp + 1); - sp += 2*sizeof(uintptr); + while(pc == (uintptr)sys·lessstack) { + pc = (uintptr)stk->gobuf.pc; + sp = stk->gobuf.sp; + stk = (Stktop*)stk->stackbase; } if(f->frame < sizeof(uintptr)) // assembly functions lie diff --git a/src/pkg/runtime/darwin/386/sys.s b/src/pkg/runtime/darwin/386/sys.s index bbcb622d5f4..fc2d8ede9c4 100644 --- a/src/pkg/runtime/darwin/386/sys.s +++ b/src/pkg/runtime/darwin/386/sys.s @@ -6,6 +6,8 @@ // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers. +#include "386/asm.h" + TEXT notok(SB),7,$0 MOVL $0xf1, 0xf1 RET @@ -26,7 +28,7 @@ TEXT exit1(SB),7,$0 CALL notok(SB) RET -TEXT sys·write(SB),7,$0 +TEXT write(SB),7,$0 MOVL $4, AX INT $0x80 JAE 2(PC) @@ -56,9 +58,10 @@ TEXT sigaction(SB),7,$0 // 16(FP) siginfo // 20(FP) context TEXT sigtramp(SB),7,$40 - MOVL 4(FS), BP // m - MOVL 28(BP), BP // m->gsignal - MOVL BP, 0(FS) // g = m->gsignal + // g = m->gsignal + MOVL m, BP + MOVL m_gsignal(BP), BP + MOVL BP, g MOVL handler+4(FP), DI MOVL signo+12(FP), AX @@ -95,11 +98,11 @@ TEXT bsdthread_create(SB),7,$32 // 0(SP) is where the caller PC would be; kernel skips it MOVL func+12(FP), BX MOVL BX, 4(SP) // func - MOVL m+4(FP), BX + MOVL mm+4(FP), BX MOVL BX, 8(SP) // arg MOVL stk+0(FP), BX MOVL BX, 12(SP) // stack - MOVL g+8(FP), BX + MOVL gg+8(FP), BX MOVL BX, 16(SP) // pthread MOVL $0x1000000, 20(SP) // flags = PTHREAD_START_CUSTOM INT $0x80 @@ -121,7 +124,7 @@ TEXT bsdthread_start(SB),7,$0 // set up ldt 7+id to point at m->tls. // m->tls is at m+40. newosproc left // the m->id in tls[0]. - LEAL 40(DX), BP + LEAL m_tls(DX), BP MOVL 0(BP), DI ADDL $7, DI // m0 is LDT#7. count up. // setldt(tls#, &tls, sizeof tls) @@ -139,9 +142,9 @@ TEXT bsdthread_start(SB),7,$0 MOVW DI, FS // Now segment is established. Initialize m, g. - MOVL AX, 0(FS) // g - MOVL DX, 4(FS) // m - MOVL BX, 20(DX) // m->procid = thread port (for debuggers) + MOVL AX, g + MOVL DX, m + MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers) CALL CX // fn() CALL exit1(SB) RET diff --git a/src/pkg/runtime/darwin/thread.c b/src/pkg/runtime/darwin/thread.c index 3a982471ae1..2a6116c103f 100644 --- a/src/pkg/runtime/darwin/thread.c +++ b/src/pkg/runtime/darwin/thread.c @@ -151,8 +151,12 @@ osinit(void) void newosproc(M *m, G *g, void *stk, void (*fn)(void)) { - // printf("newosproc m=%p g=%p stk=%p fn=%p\n", m, g, stk, fn); m->tls[0] = m->id; // so 386 asm can find it + + 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); + } bsdthread_create(stk, m, g, fn); } diff --git a/src/pkg/runtime/linux/386/sys.s b/src/pkg/runtime/linux/386/sys.s index 419973a5ca9..fa056c075da 100755 --- a/src/pkg/runtime/linux/386/sys.s +++ b/src/pkg/runtime/linux/386/sys.s @@ -6,6 +6,8 @@ // System calls and other sys.stuff for 386, Linux // +#include "386/asm.h" + TEXT syscall(SB),7,$0 MOVL 4(SP), AX // syscall number MOVL 8(SP), BX // arg1 @@ -42,26 +44,6 @@ TEXT write(SB),7,$0 INT $0x80 RET -TEXT getpid(SB),7,$0 - MOVL $20, AX - INT $0x80 - RET - -TEXT kill(SB),7,$0 - MOVL $37, AX - MOVL 4(SP), BX - MOVL 8(SP), CX - INT $0x80 - RET - -TEXT sys·write(SB),7,$0 - MOVL $4, AX // syscall - write - MOVL 4(SP), BX - MOVL 8(SP), CX - MOVL 12(SP), DX - INT $0x80 - RET - TEXT rt_sigaction(SB),7,$0 MOVL $174, AX // syscall - rt_sigaction MOVL 4(SP), BX @@ -72,18 +54,19 @@ TEXT rt_sigaction(SB),7,$0 RET TEXT sigtramp(SB),7,$0 - MOVL 4(FS), BP // m - MOVL 20(BP), AX // m->gsignal - MOVL AX, 0(FS) // g = m->gsignal + MOVL m, BP + MOVL m_gsignal(BP), AX + MOVL AX, g JMP sighandler(SB) TEXT sigignore(SB),7,$0 RET TEXT sigreturn(SB),7,$0 - MOVL 4(FS), BP // m - MOVL 32(BP), BP // m->curg - MOVL BP, 0(FS) // g = m->curg + // g = m->curg + MOVL m, BP + MOVL m_curg(BP), BP + MOVL BP, g MOVL $173, AX // rt_sigreturn INT $0x80 INT $3 // not reached @@ -104,7 +87,7 @@ TEXT sys·mmap(SB),7,$0 INT $3 RET -// int64 futex(int32 *uaddr, int32 op, int32 val, +// int32 futex(int32 *uaddr, int32 op, int32 val, // struct timespec *timeout, int32 *uaddr2, int32 val2); TEXT futex(SB),7,$0 MOVL $240, AX // futex @@ -117,22 +100,24 @@ TEXT futex(SB),7,$0 INT $0x80 RET -// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void)); +// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void)); TEXT clone(SB),7,$0 MOVL $120, AX // clone MOVL flags+4(SP), BX MOVL stack+8(SP), CX + MOVL $0, DX // parent tid ptr + MOVL $0, DI // child tid ptr // Copy m, g, fn off parent stack for use by child. - SUBL $12, CX - MOVL m+12(SP), DX - MOVL DX, 0(CX) - MOVL g+16(SP), DX - MOVL DX, 4(CX) - MOVL fn+20(SP), DX - MOVL DX, 8(CX) + SUBL $16, CX + MOVL mm+12(SP), SI + MOVL SI, 0(CX) + MOVL gg+16(SP), SI + MOVL SI, 4(CX) + MOVL fn+20(SP), SI + MOVL SI, 8(CX) + MOVL $1234, 12(CX) - MOVL $120, AX INT $0x80 // In parent, return. @@ -140,29 +125,58 @@ TEXT clone(SB),7,$0 JEQ 2(PC) RET - // In child, set up new stack, etc. - MOVL 0(CX), BX // m - MOVL 12(AX), AX // fs (= m->cret) - MOVW AX, FS - MOVL 8(CX), DX // fn - ADDL $12, CX - MOVL CX, SP + // Paranoia: check that SP is as we expect. + MOVL 12(SP), BP + CMPL BP, $1234 + JEQ 2(PC) + INT $3 - // fn is now on top of stack. - - // initialize m->procid to Linux tid + // Initialize AX to Linux tid MOVL $224, AX INT $0x80 - MOVL AX, 20(BX) - // call fn - CALL DX + // In child on new stack. Reload registers (paranoia). + MOVL 0(SP), BX // m + MOVL 4(SP), DX // g + MOVL 8(SP), CX // fn - // It shouldn't return; if it does, exit. - MOVL $111, DI - MOVL $1, AX - INT $0x80 - JMP -3(PC) // keep exiting + MOVL AX, m_procid(BX) // save tid as m->procid + + // set up ldt 7+id to point at m->tls. + // m->tls is at m+40. newosproc left the id in tls[0]. + LEAL m_tls(BX), BP + MOVL 0(BP), DI + ADDL $7, DI // m0 is LDT#7. count up. + // setldt(tls#, &tls, sizeof tls) + PUSHAL // save registers + PUSHL $32 // sizeof tls + PUSHL BP // &tls + PUSHL DI // tls # + CALL setldt(SB) + POPL AX + POPL AX + POPL AX + POPAL + SHLL $3, DI // segment# is ldt*8 + 7 (different 7 than above) + ADDL $7, DI + MOVW DI, FS + + // Now segment is established. Initialize m, g. + MOVL DX, g + MOVL BX, m + + MOVL 0(DX), DX // paranoia; check they are not nil + MOVL 0(BX), BX + + // more paranoia; check that stack splitting code works + PUSHAL + CALL emptyfunc(SB) + POPAL + + CALL CX // fn() + CALL exit1(SB) + MOVL $0x1234, 0x1005 + RET TEXT sigaltstack(SB),7,$-8 MOVL $186, AX // sigaltstack @@ -174,10 +188,6 @@ TEXT sigaltstack(SB),7,$-8 INT $3 RET -// // fake the per-goroutine and per-mach registers -// LEAL m0(SB), - -// TODO(rsc): move to linux.s // // struct user_desc { // unsigned int entry_number; diff --git a/src/pkg/runtime/linux/os.h b/src/pkg/runtime/linux/os.h index c6161936760..c36813a9bfb 100644 --- a/src/pkg/runtime/linux/os.h +++ b/src/pkg/runtime/linux/os.h @@ -3,8 +3,8 @@ // license that can be found in the LICENSE file. // Linux-specific system calls -int64 futex(uint32*, int32, uint32, Timespec*, uint32*, uint32); -int64 clone(int32, void*, M*, G*, void(*)(void)); +int32 futex(uint32*, int32, uint32, Timespec*, uint32*, uint32); +int32 clone(int32, void*, M*, G*, void(*)(void)); struct Sigaction; void rt_sigaction(int64, struct Sigaction*, void*, uint64); diff --git a/src/pkg/runtime/linux/thread.c b/src/pkg/runtime/linux/thread.c index cc9ba161bfd..a1d927c7bb7 100644 --- a/src/pkg/runtime/linux/thread.c +++ b/src/pkg/runtime/linux/thread.c @@ -42,7 +42,7 @@ static Timespec longtime = static void futexsleep(uint32 *addr, uint32 val) { - int64 ret; + int32 ret; ret = futex(addr, FUTEX_WAIT, val, &longtime, nil, 0); if(ret >= 0 || ret == -EAGAIN || ret == -EINTR) @@ -234,7 +234,7 @@ enum void newosproc(M *m, G *g, void *stk, void (*fn)(void)) { - int64 ret; + int32 ret; int32 flags; /* @@ -248,21 +248,14 @@ newosproc(M *m, G *g, void *stk, void (*fn)(void)) | CLONE_THREAD /* revisit - okay for now */ ; + m->tls[0] = m->id; // so 386 asm can find it if(0){ - prints("newosproc stk="); - sys·printpointer(stk); - prints(" m="); - sys·printpointer(m); - prints(" g="); - sys·printpointer(g); - prints(" fn="); - sys·printpointer(fn); - prints(" clone="); - sys·printpointer(clone); - prints("\n"); + printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n", + stk, m, g, fn, clone, m->id, m->tls[0], &m); } ret = clone(flags, stk, m, g, fn); + if(ret < 0) *(int32*)123 = 123; }