diff options
| author | Russ Cox <rsc@golang.org> | 2010-07-17 16:54:03 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2010-07-17 16:54:03 -0700 |
| commit | 2d6ae385e1c097a061fdc6de9e771d7ad9dbcc0e (patch) | |
| tree | afe29059cf64c087aada3ea31b9d84eac27edbc3 /src/pkg/runtime | |
| parent | bc2ee6b8c641010a576aa991c84120e0b991f2c3 (diff) | |
| download | go-2d6ae385e1c097a061fdc6de9e771d7ad9dbcc0e.tar.xz | |
linux/386: use Xen-friendly ELF TLS instruction sequence
Fixes #465.
R=iant
CC=golang-dev
https://golang.org/cl/1665051
Diffstat (limited to 'src/pkg/runtime')
| -rw-r--r-- | src/pkg/runtime/linux/386/sys.s | 11 | ||||
| -rwxr-xr-x | src/pkg/runtime/mkasmh.sh | 25 |
2 files changed, 32 insertions, 4 deletions
diff --git a/src/pkg/runtime/linux/386/sys.s b/src/pkg/runtime/linux/386/sys.s index 57ffc4aa4f..35c3780cef 100644 --- a/src/pkg/runtime/linux/386/sys.s +++ b/src/pkg/runtime/linux/386/sys.s @@ -161,12 +161,12 @@ TEXT clone(SB),7,$0 // In child on new stack. Reload registers (paranoia). MOVL 0(SP), BX // m MOVL 4(SP), DX // g - MOVL 8(SP), CX // fn + MOVL 8(SP), SI // fn 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]. + // 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. @@ -186,7 +186,7 @@ TEXT clone(SB),7,$0 MOVL DX, g(AX) MOVL BX, m(AX) - CALL stackcheck(SB) // smashes AX + CALL stackcheck(SB) // smashes AX, CX MOVL 0(DX), DX // paranoia; check they are not nil MOVL 0(BX), BX @@ -195,7 +195,7 @@ TEXT clone(SB),7,$0 CALL emptyfunc(SB) POPAL - CALL CX // fn() + CALL SI // fn() CALL exit1(SB) MOVL $0x1234, 0x1005 RET @@ -247,8 +247,11 @@ TEXT setldt(SB),7,$32 * To accommodate that rewrite, we translate * the address here and bump the limit to 0xffffffff (no limit) * so that -8(GS) maps to 0(address). + * Also, the final 0(GS) (current 8(CX)) has to point + * to itself, to mimic ELF. */ ADDL $0x8, CX // address + MOVL CX, 0(CX) // set up user_desc LEAL 16(SP), AX // struct user_desc diff --git a/src/pkg/runtime/mkasmh.sh b/src/pkg/runtime/mkasmh.sh index aae773cfee..df8ad88381 100755 --- a/src/pkg/runtime/mkasmh.sh +++ b/src/pkg/runtime/mkasmh.sh @@ -24,6 +24,31 @@ case "$GOARCH" in echo '#define g(r) 0(r)' echo '#define m(r) 4(r)' ;; + linux) + # On Linux systems, what we call 0(GS) and 4(GS) for g and m + # turn into %gs:-8 and %gs:-4 (using gcc syntax to denote + # what the machine sees as opposed to 8l input). + # 8l rewrites 0(GS) and 4(GS) into these. + # + # On Linux Xen, it is not allowed to use %gs:-8 and %gs:-4 + # directly. Instead, we have to store %gs:0 into a temporary + # register and then use -8(%reg) and -4(%reg). This kind + # of addressing is correct even when not running Xen. + # + # 8l can rewrite MOVL 0(GS), CX into the appropriate pair + # of mov instructions, using CX as the intermediate register + # (safe because CX is about to be written to anyway). + # But 8l cannot handle other instructions, like storing into 0(GS), + # which is where these macros come into play. + # get_tls sets up the temporary and then g and r use it. + # + # The final wrinkle is that get_tls needs to read from %gs:0, + # but in 8l input it's called 8(GS), because 8l is going to + # subtract 8 from all the offsets, as described above. + echo '#define get_tls(r) MOVL 8(GS), r' + echo '#define g(r) -8(r)' + echo '#define m(r) -4(r)' + ;; *) echo '#define get_tls(r)' echo '#define g(r) 0(GS)' |
