Commit decd8109 authored by Aram Hăvărneanu's avatar Aram Hăvărneanu Committed by Dave Cheney

liblink, runtime: preliminary support for plan9/amd64

A TLS slot is reserved by _rt0_.*_plan9 as an automatic and
its address (which is static on Plan 9) is saved in the
global _privates symbol. The startup linkage now is exactly
like that from Plan 9 libc, and the way we access g is
exactly as if we'd have used privalloc(2).

Aside from making the code more standard, this change
drastically simplifies it, both for 386 and for amd64, and
makes the Plan 9 code in liblink common for both 386 and
amd64.

The amd64 runtime code was cleared of nxm assumptions, and
now runs on the standard Plan 9 kernel.

Note handling fixes will follow in a separate CL.

LGTM=rsc
R=golang-codereviews, rsc, bradfitz, dave
CC=0intro, ality, golang-codereviews, jas, minux.ma, mischief
https://golang.org/cl/101510049
parent d7b678b2
......@@ -391,7 +391,7 @@ struct Link
LSym* sym_modu;
LSym* symmorestack[20];
LSym* tlsg;
LSym* plan9tos;
LSym* plan9privates;
Prog* curp;
Prog* printp;
Prog* blitrl;
......
......@@ -1901,7 +1901,6 @@ prefixof(Link *ctxt, Addr *a)
case Hlinux:
case Hnetbsd:
case Hopenbsd:
case Hplan9:
case Hsolaris:
return 0x64; // FS
case Hdarwin:
......@@ -3365,6 +3364,19 @@ mfound:
default:
sysfatal("unknown TLS base location for %s", headstr(ctxt->headtype));
case Hplan9:
if(ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
memset(&pp.from, 0, sizeof pp.from);
pp.from.type = D_EXTERN;
pp.from.sym = ctxt->plan9privates;
pp.from.offset = 0;
pp.from.index = D_NONE;
ctxt->rexflag |= Pw;
*ctxt->andptr++ = 0x8B;
asmand(ctxt, &pp.from, &p->to);
break;
case Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c.
// TLS base is 0(FS).
pp.from = p->from;
......
......@@ -2707,11 +2707,11 @@ mfound:
break;
case Hplan9:
if(ctxt->plan9tos == nil)
ctxt->plan9tos = linklookup(ctxt, "_tos", 0);
if(ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
memset(&pp.from, 0, sizeof pp.from);
pp.from.type = D_EXTERN;
pp.from.sym = ctxt->plan9tos;
pp.from.sym = ctxt->plan9privates;
pp.from.offset = 0;
pp.from.index = D_NONE;
*ctxt->andptr++ = 0x8B;
......
......@@ -103,7 +103,7 @@ static int
canuselocaltls(Link *ctxt)
{
switch(ctxt->headtype) {
// case Hlinux:
case Hplan9:
case Hwindows:
return 0;
}
......@@ -402,6 +402,10 @@ addstacksplit(Link *ctxt, LSym *cursym)
for(i=0; i<nelem(morename); i++)
ctxt->symmorestack[i] = linklookup(ctxt, morename[i], 0);
}
if(ctxt->headtype == Hplan9 && ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
ctxt->cursym = cursym;
if(cursym->text == nil || cursym->text->link == nil)
......
......@@ -270,8 +270,8 @@ addstacksplit(Link *ctxt, LSym *cursym)
ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
}
if(ctxt->headtype == Hplan9 && ctxt->plan9tos == nil)
ctxt->plan9tos = linklookup(ctxt, "_tos", 0);
if(ctxt->headtype == Hplan9 && ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
ctxt->cursym = cursym;
......
......@@ -128,8 +128,6 @@ linknew(LinkArch *arch)
default:
sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype));
case Hplan9:
ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
break;
case Hwindows:
break;
case Hlinux:
......
......@@ -11,8 +11,12 @@ enum {
#else
#ifdef GOOS_windows
RuntimeGogoBytes = 80,
#else
#ifdef GOOS_plan9
RuntimeGogoBytes = 80,
#else
RuntimeGogoBytes = 64,
#endif // Plan 9
#endif // Windows
#endif // Solaris
PhysPageSize = 4096,
......
#define PAGESIZE 0x200000ULL
#define PAGESIZE 0x1000
typedef struct Ureg Ureg;
......
......@@ -5,44 +5,17 @@
#include "../../cmd/ld/textflag.h"
// void runtime·memclr(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-16
MOVQ ptr+0(FP), DI
MOVQ n+8(FP), BX
XORQ AX, AX
clr_tail:
TESTQ BX, BX
JEQ clr_0
CMPQ BX, $2
JBE clr_1or2
CMPQ BX, $4
JBE clr_3or4
CMPQ BX, $8
JBE clr_5through8
CMPQ BX, $16
JBE clr_9through16
MOVQ BX, CX
SHRQ $2, CX
TEXT runtime·memclr(SB),NOSPLIT,$0-16
MOVQ addr+0(FP), DI
MOVQ count+8(FP), CX
MOVQ CX, BX
ANDQ $7, BX
SHRQ $3, CX
MOVQ $0, AX
CLD
REP
STOSQ
ANDQ $3, BX
JNE clr_tail
RET
clr_1or2:
MOVB AX, (DI)
MOVB AX, -1(DI)(BX*1)
clr_0:
RET
clr_3or4:
MOVW AX, (DI)
MOVW AX, -2(DI)(BX*1)
RET
clr_5through8:
MOVL AX, (DI)
MOVL AX, -4(DI)(BX*1)
RET
clr_9through16:
MOVQ AX, (DI)
MOVQ AX, -8(DI)(BX*1)
MOVQ BX, CX
REP
STOSB
RET
......@@ -146,6 +146,35 @@ runtime·usleep(uint32 µs)
runtime·sleep(ms);
}
#pragma textflag NOSPLIT
int64
runtime·nanotime(void)
{
static int32 fd = -1;
byte b[8];
uint32 hi, lo;
// As long as all goroutines share the same file
// descriptor table we can get away with using
// just a static fd. Without a lock the file can
// be opened twice but that's okay.
//
// Using /dev/bintime gives us a latency on the
// order of ten microseconds between two calls.
//
// The naïve implementation (without the cached
// file descriptor) is roughly four times slower
// in 9vx on a 2.16 GHz Intel Core 2 Duo.
if(fd < 0 && (fd = runtime·open("/dev/bintime", OREAD|OCEXEC, 0)) < 0)
return 0;
if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
return 0;
hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
return (int64)hi<<32 | (int64)lo;
}
void
time·now(int64 sec, int32 nsec)
{
......
......@@ -4,39 +4,20 @@
#include "../../cmd/ld/textflag.h"
TEXT _rt0_386_plan9(SB),NOSPLIT, $0
TEXT _rt0_386_plan9(SB),NOSPLIT,$12
MOVL AX, _tos(SB)
// move arguments down to make room for
// m and g at top of stack, right before Tos.
MOVL SP, SI
SUBL $8, SP
MOVL SP, DI
MOVL AX, CX
SUBL SI, CX
CLD
REP; MOVSB
// adjust argv
SUBL SI, DI
MOVL newargc+0(SP), CX
LEAL newargv+4(SP), BP
argv_fix:
ADDL DI, 0(BP)
ADDL $4, BP
LOOP argv_fix
LEAL 8(SP), AX
MOVL AX, _privates(SB)
MOVL $1, _nprivates(SB)
CALL runtime·asminit(SB)
MOVL 0(SP), AX
LEAL 4(SP), BX
PUSHL BX
PUSHL AX
PUSHL $-1
JMP _rt0_go(SB)
MOVL inargc-4(FP), AX
MOVL AX, 0(SP)
LEAL inargv+0(FP), AX
MOVL AX, 4(SP)
CALL _rt0_go(SB)
DATA runtime·isplan9(SB)/4, $1
GLOBL runtime·isplan9(SB), $4
GLOBL _tos(SB), $4
GLOBL _privates(SB), $4
GLOBL _nprivates(SB), $4
......@@ -4,11 +4,18 @@
#include "../../cmd/ld/textflag.h"
TEXT _rt0_amd64_plan9(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
MOVQ 0(SP), DI // argc
TEXT _rt0_amd64_plan9(SB),NOSPLIT,$24
MOVQ AX, _tos(SB)
LEAQ 16(SP), AX
MOVQ AX, _privates(SB)
MOVL $1, _nprivates(SB)
MOVL inargc-8(FP), DI
LEAQ inargv+0(FP), SI
MOVQ $_rt0_go(SB), AX
JMP AX
DATA runtime·isplan9(SB)/4, $1
GLOBL runtime·isplan9(SB), $4
GLOBL _tos(SB), $8
GLOBL _privates(SB), $8
GLOBL _nprivates(SB), $4
......@@ -101,7 +101,7 @@ TEXT runtime·rfork(SB),NOSPLIT,$0
MOVL BX, g_m(DX)
// Initialize procid from TOS struct.
// TODO: Be explicit and insert a new MOVL _tos(SB), AX here.
MOVL _tos(SB), AX
MOVL 48(AX), AX // procid
MOVL AX, m_procid(BX) // save pid as m->procid
......
......@@ -10,26 +10,22 @@ TEXT runtime·setldt(SB),NOSPLIT,$0
RET
TEXT runtime·open(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $14, BP
SYSCALL
RET
TEXT runtime·pread(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $50, BP
SYSCALL
RET
TEXT runtime·pwrite(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $51, BP
SYSCALL
RET
// int32 _seek(int64*, int32, int64, int32)
TEXT _seek<>(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $39, BP
SYSCALL
RET
......@@ -52,67 +48,51 @@ TEXT runtime·seek(SB),NOSPLIT,$56
RET
TEXT runtime·close(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $4, BP
SYSCALL
RET
TEXT runtime·exits(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $8, BP
SYSCALL
RET
TEXT runtime·brk_(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $24, BP
SYSCALL
RET
TEXT runtime·sleep(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $17, BP
SYSCALL
RET
TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $37, BP
SYSCALL
RET
TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $52, BP
SYSCALL
RET
TEXT runtime·notify(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $28, BP
SYSCALL
RET
TEXT runtime·noted(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $29, BP
SYSCALL
RET
TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $38, BP
SYSCALL
RET
TEXT runtime·nanotime(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $60, BP
SYSCALL
RET
TEXT runtime·rfork(SB),NOSPLIT,$0
MOVQ $0x8000, AX
MOVQ $19, BP // rfork
SYSCALL
......@@ -135,8 +115,9 @@ TEXT runtime·rfork(SB),NOSPLIT,$0
MOVQ DX, g(AX)
MOVQ BX, g_m(DX)
// Initialize AX from pid in TLS.
MOVQ 0(FS), AX
// Initialize procid from TOS struct.
MOVQ _tos(SB), AX
MOVQ 64(AX), AX
MOVQ AX, m_procid(BX) // save pid as m->procid
CALL runtime·stackcheck(SB) // smashes AX, CX
......@@ -224,7 +205,6 @@ TEXT runtime·errstr(SB),NOSPLIT,$0
MOVQ m_errstr(BX), CX
MOVQ CX, 8(SP)
MOVQ $ERRMAX, 16(SP)
MOVQ $0x8000, AX
MOVQ $41, BP
SYSCALL
......
// Copyright 2010 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 "os_GOOS.h"
#include "../../cmd/ld/textflag.h"
#pragma textflag NOSPLIT
int64
runtime·nanotime(void)
{
static int32 fd = -1;
byte b[8];
uint32 hi, lo;
// As long as all goroutines share the same file
// descriptor table we can get away with using
// just a static fd. Without a lock the file can
// be opened twice but that's okay.
//
// Using /dev/bintime gives us a latency on the
// order of ten microseconds between two calls.
//
// The naïve implementation (without the cached
// file descriptor) is roughly four times slower
// in 9vx on a 2.16 GHz Intel Core 2 Duo.
if(fd < 0 && (fd = runtime·open("/dev/bintime", OREAD|OCEXEC, 0)) < 0)
return 0;
if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
return 0;
hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
return (int64)hi<<32 | (int64)lo;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment