update 386 to new runtime (CL 30381)

R=r
DELTA=298  (119 added, 81 deleted, 98 changed)
OCL=30427
CL=30443
This commit is contained in:
Russ Cox 2009-06-17 15:15:55 -07:00
parent 7343e03c43
commit 8522a478bb
9 changed files with 209 additions and 171 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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
// <asm-i386/ldt.h>
// struct user_desc {
// unsigned int entry_number;

View File

@ -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);

View File

@ -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;
}