]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add demo running Go on raw (emulated) hw
authorRuss Cox <rsc@golang.org>
Thu, 14 Jan 2010 03:51:59 +0000 (19:51 -0800)
committerRuss Cox <rsc@golang.org>
Thu, 14 Jan 2010 03:51:59 +0000 (19:51 -0800)
8l: add GOOS=pchw, stop spelling out all the elf numbers.

R=r
CC=golang-dev
https://golang.org/cl/186144

18 files changed:
src/cmd/8l/asm.c
src/cmd/8l/obj.c
src/cmd/ld/elf.c
src/cmd/ld/elf.h
src/pkg/runtime/Makefile
src/pkg/runtime/pchw/386/defs.h [new file with mode: 0644]
src/pkg/runtime/pchw/386/rt0.s [new file with mode: 0644]
src/pkg/runtime/pchw/386/signal.c [new file with mode: 0644]
src/pkg/runtime/pchw/386/sys.s [new file with mode: 0644]
src/pkg/runtime/pchw/README [new file with mode: 0755]
src/pkg/runtime/pchw/bootblock [new file with mode: 0755]
src/pkg/runtime/pchw/dot-bochsrc [new file with mode: 0644]
src/pkg/runtime/pchw/io.go [new file with mode: 0644]
src/pkg/runtime/pchw/mem.c [new file with mode: 0644]
src/pkg/runtime/pchw/os.h [new file with mode: 0644]
src/pkg/runtime/pchw/signals.h [new file with mode: 0644]
src/pkg/runtime/pchw/thread.c [new file with mode: 0644]
src/pkg/runtime/symtab.c

index 73ceeba6efa3abdad944c927b344ca436550f9ca..005634e42992fbcecb92b85654a6da037537c7b7 100644 (file)
@@ -275,7 +275,7 @@ doelf(void)
        Sym *s, *shstrtab, *dynamic, *dynstr, *d;
        int h, nsym, t;
 
-       if(HEADTYPE != 7 && HEADTYPE != 8 && HEADTYPE != 9)
+       if(!iself)
                return;
 
        /* predefine strings we need for section headers */
@@ -504,6 +504,8 @@ asmb(void)
 
        switch(HEADTYPE) {
        default:
+               if(iself)
+                       goto Elfseek;
                diag("unknown header type %d", HEADTYPE);
        case 0:
                seek(cout, rnd(HEADR+textsize, 8192), 0);
@@ -529,9 +531,7 @@ asmb(void)
                }
                cflush();
                break;
-       case 7:
-       case 8:
-       case 9:
+       Elfseek:
        case 10:
                v = rnd(HEADR+textsize, INITRND);
                seek(cout, v, 0);
@@ -570,6 +570,8 @@ asmb(void)
                Bflush(&bso);
                switch(HEADTYPE) {
                default:
+                       if(iself)
+                               goto Elfsym;
                case 0:
                        seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
                        break;
@@ -587,9 +589,7 @@ asmb(void)
                case 6:
                        symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink;
                        break;
-               case 7:
-               case 8:
-               case 9:
+               Elfsym:
                case 10:
                        symo = rnd(HEADR+textsize, INITRND)+datsize;
                        symo = rnd(symo, INITRND);
@@ -627,6 +627,8 @@ asmb(void)
        seek(cout, 0L, 0);
        switch(HEADTYPE) {
        default:
+               if(iself)
+                       goto Elfput;
        case 0: /* garbage */
                lput(0x160L<<16);               /* magic and sections */
                lput(0L);                       /* time and date */
@@ -760,11 +762,9 @@ asmb(void)
                asmbmacho(symdatva, symo);
                break;
 
-       case 7:
-       case 8:
-       case 9:
+       Elfput:
                /* elf 386 */
-               if(HEADTYPE == 8)
+               if(HEADTYPE == 8 || HEADTYPE == 11)
                        debug['d'] = 1;
 
                eh = getElfEhdr();
@@ -833,7 +833,7 @@ asmb(void)
                ph->memsz = w+bsssize;
                ph->align = INITRND;
 
-               if(!debug['s'] && HEADTYPE != 8) {
+               if(!debug['s'] && HEADTYPE != 8 && HEADTYPE != 11) {
                        ph = newElfPhdr();
                        ph->type = PT_LOAD;
                        ph->flags = PF_W+PF_R;
index 89ddf0313ec3e3fdcc8aba17d9d355375441d3d6..5918b0e8016d9504be75b0e79018e6580171c8cc 100644 (file)
@@ -164,6 +164,9 @@ main(int argc, char *argv[])
                else
                if(strcmp(goos, "mingw") == 0)
                        HEADTYPE = 10;
+               else
+               if(strcmp(goos, "pchw") == 0)
+                       HEADTYPE = 11;
                else
                        print("goos is not known: %s\n", goos);
        }
@@ -283,6 +286,17 @@ main(int argc, char *argv[])
                if(INITRND == -1)
                        INITRND = PEALIGN;
                break;
+       case 11:
+               tlsoffset = 0;
+               elfinit();
+               HEADR = ELFRESERVE;
+               if(INITTEXT == -1)
+                       INITTEXT = 0x100000+HEADR;
+               if(INITDAT == -1)
+                       INITDAT = 0;
+               if(INITRND == -1)
+                       INITRND = 4096;
+               break;
        }
        if(INITDAT != 0 && INITRND != 0)
                print("warning: -D0x%lux is ignored because of -R0x%lux\n",
index c57630e8081b75d1466fddf5820f99563d6db2dc..d2adca16ce64d5225c985c28da780052e2908184 100644 (file)
@@ -13,6 +13,8 @@
  */
 #define        NSECT   32
 
+int    iself;
+
 static int     elf64;
 static ElfEhdr hdr;
 static ElfPhdr *phdr[NSECT];
@@ -26,6 +28,8 @@ static        char    *interp;
 void
 elfinit(void)
 {
+       iself = 1;
+
        switch(thechar) {
        // 64-bit architectures
        case '6':
index 9f18ec3ddc47309a78ce59dff9e018616979727c..cd78f2d9ccecbe8e601de6af29241749401ba7cf 100644 (file)
@@ -961,6 +961,7 @@ uint64      startelf(void);
 uint64 endelf(void);
 extern int     numelfphdr;
 extern int     numelfshdr;
+extern int     iself;
 int    elfwriteinterp(void);
 void   elfinterp(ElfShdr*, uint64, char*);
 
index 370a97309f6c568da520922e5a78180726f51762..91154764af6ec904b1cc3a97232ec1961e2e1418 100644 (file)
@@ -24,6 +24,9 @@ GOFILES=\
        extern.go\
        type.go\
 
+GOFILES_pchw=\
+       pchw/io.go\
+
 # 386-specific object files
 OFILES_386=\
        vlop.$O\
diff --git a/src/pkg/runtime/pchw/386/defs.h b/src/pkg/runtime/pchw/386/defs.h
new file mode 100644 (file)
index 0000000..5df7576
--- /dev/null
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/pkg/runtime/pchw/386/rt0.s b/src/pkg/runtime/pchw/386/rt0.s
new file mode 100644 (file)
index 0000000..d03fc2d
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+TEXT _rt0_386_pchw(SB), 7, $0
+       // Disable interrupts.
+       CLI
+       
+       // Establish stack.
+       MOVL    $0x10000, AX
+       MOVL    AX, SP
+       
+       // Set up memory hardware.
+       CALL    msetup(SB)
+
+       // _rt0_386 expects to find argc, argv, envv on stack.
+       // Set up argv=["kernel"] and envv=[].
+       SUBL    $64, SP
+       MOVL    $1, 0(SP)
+       MOVL    $kernel(SB), 4(SP)
+       MOVL    $0, 8(SP)
+       MOVL    $0, 12(SP)
+       JMP     _rt0_386(SB)
+
+DATA kernel+0(SB)/7, $"kernel\z"
+GLOBL kernel(SB), $7
+       
+
diff --git a/src/pkg/runtime/pchw/386/signal.c b/src/pkg/runtime/pchw/386/signal.c
new file mode 100644 (file)
index 0000000..5df7576
--- /dev/null
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/pkg/runtime/pchw/386/sys.s b/src/pkg/runtime/pchw/386/sys.s
new file mode 100644 (file)
index 0000000..c51a5ec
--- /dev/null
@@ -0,0 +1,92 @@
+// 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.
+
+// Manipulation of segment tables.
+//
+// Descriptor entry format for system call
+// is the native machine format, ugly as it is:
+//
+//     2-byte limit
+//     3-byte base
+//     1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
+//     1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
+//             0x0F=4 more bits of limit
+//     1 byte: 8 more bits of base
+
+// Called to set up memory hardware.
+// Already running in 32-bit mode thanks to boot block,
+// but we need to install our new GDT that we can modify.
+TEXT msetup(SB), 7, $0
+       MOVL    gdtptr(SB), GDTR
+       MOVL    $(1*8+0), AX
+       MOVW    AX, DS
+       MOVW    AX, ES
+       MOVW    AX, SS
+       MOVW    $0, AX
+       MOVW    AX, FS
+       MOVW    AX, GS
+
+       // long jmp to cs:mret
+       BYTE    $0xEA
+       LONG $mret(SB)
+       WORD $(2*8+0)
+       
+TEXT mret(SB), 7, $0
+       RET
+
+// GDT memory
+TEXT gdt(SB), 7, $0
+       // null segment
+       LONG    $0
+       LONG    $0
+       
+       // 4GB data segment
+       LONG    $0xFFFF
+       LONG    $0x00CF9200
+
+       // 4GB code segment
+       LONG    $0xFFFF
+       LONG    $0x00CF9A00
+
+       // null segment (will be thread-local storage segment)
+       LONG    $0
+       LONG    $0
+
+// GDT pseudo-descriptor
+TEXT gdtptr(SB), 7, $0
+       WORD    $(4*8)
+       LONG    $gdt(SB)
+
+// Called to establish the per-thread segment.
+// Write to gdt[3] and reload the gdt register.
+// setldt(int entry, int address, int limit)
+TEXT setldt(SB),7,$32
+       MOVL    address+4(FP), BX       // aka base
+       MOVL    limit+8(FP), CX
+
+       // set up segment descriptor
+       LEAL    gdt+(3*8)(SB), AX       // gdt entry #3
+       MOVL    $0, 0(AX)
+       MOVL    $0, 4(AX)
+
+       MOVW    BX, 2(AX)
+       SHRL    $16, BX
+       MOVB    BX, 4(AX)
+       SHRL    $8, BX
+       MOVB    BX, 7(AX)
+
+       MOVW    CX, 0(AX)
+       SHRL    $16, CX
+       ANDL    $0x0F, CX
+       ORL     $0x40, CX               // 32-bit operand size
+       MOVB    CX, 6(AX)
+       MOVB    $0xF2, 5(AX)    // r/w data descriptor, dpl=3, present
+
+       MOVL    gdtptr(SB), GDTR
+
+       // Compute segment selector - (entry*8+0)
+       MOVL    $(3*8+0), AX
+       MOVW    AX, GS
+       RET
+
diff --git a/src/pkg/runtime/pchw/README b/src/pkg/runtime/pchw/README
new file mode 100755 (executable)
index 0000000..4987f58
--- /dev/null
@@ -0,0 +1,53 @@
+This directory contains a simple example of how one might
+start Go running on bare hardware.  It is very primitive but
+can run go/test/sieve.go, the concurrent prime sieve, on a
+uniprocessor.  It has only been tested using the Bochs emulator.
+
+To run, first build the tools by running all.bash with GOARCH=386
+and GOOS set to your normal GOOS (linux, darwin).  Then:
+
+       export GOOS=pchw
+       cd $GOROOT/src/pkg/runtime
+       make clean
+       make install
+       cd pchw
+       8g $GOROOT/test/sieve.go
+       8l sieve.8
+       8l -a sieve.8 >sieve.asm        # can consult sieve.asm for debugging
+       dd if=/dev/zero of=disk count=10000
+       cat bootblock 8.out | dd of=disk conv=notrunc
+       bochs
+
+You may have to tweak the .bochsrc depending on your system,
+and you may need to install the Bochs emulator.
+
+
+
+The bootblock is from MIT's xv6 project and carries this notice:
+
+    The xv6 software is:
+    
+    Copyright (c) 2006-2009 Frans Kaashoek, Robert Morris, Russ Cox,
+                            Massachusetts Institute of Technology
+    
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+    
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+http://pdos.csail.mit.edu/6.828/xv6/
+
diff --git a/src/pkg/runtime/pchw/bootblock b/src/pkg/runtime/pchw/bootblock
new file mode 100755 (executable)
index 0000000..54dd7c6
Binary files /dev/null and b/src/pkg/runtime/pchw/bootblock differ
diff --git a/src/pkg/runtime/pchw/dot-bochsrc b/src/pkg/runtime/pchw/dot-bochsrc
new file mode 100644 (file)
index 0000000..3f5c813
--- /dev/null
@@ -0,0 +1,18 @@
+romimage: file=$BXSHARE/BIOS-bochs-latest
+cpu: count=1, ips=100000000, reset_on_triple_fault=0
+megs: 32
+vgaromimage: file=/usr/share/vgabios/vgabios.bin
+vga: extension=none
+ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
+ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
+ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
+ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
+ata0-master: type=disk, mode=flat, path="disk", cylinders=100, heads=10, spt=10
+boot: disk
+panic: action=ask
+error: action=report
+info: action=report
+debug: action=ignore
+debugger_log: -
+config_interface: wx
+display_library: wx
diff --git a/src/pkg/runtime/pchw/io.go b/src/pkg/runtime/pchw/io.go
new file mode 100644 (file)
index 0000000..f30e688
--- /dev/null
@@ -0,0 +1,53 @@
+// 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.
+
+// Simple CGA screen output
+
+package runtime
+
+import "unsafe"
+
+var crt *[25 * 80]uint16
+var pos int
+
+func putc(c int) {
+       const (
+               port  = 0x3d4
+               color = 0x0700 // white on black
+       )
+
+       if crt == nil {
+               // init on demand in case printf is called before
+               // initialization runs.
+               var mem uintptr = 0xb8000
+               crt = (*[25 * 80]uint16)(unsafe.Pointer(mem))
+               pos = 0
+               for i := range crt[0:] {
+                       crt[i] = 0
+               }
+       }
+
+       switch c {
+       case '\n':
+               pos += 80 - pos%80
+       default:
+               crt[pos] = uint16(c&0xff | color)
+               pos++
+       }
+
+       if pos/80 >= 24 {
+               copy(crt[0:], crt[80:])
+               pos -= 80
+               for i := 0; i < 80; i++ {
+                       crt[24*80+i] = 0
+               }
+       }
+       crt[pos] = ' ' | color
+}
+
+func write(fd int32, b []byte) {
+       for _, c := range b {
+               putc(int(c))
+       }
+}
diff --git a/src/pkg/runtime/pchw/mem.c b/src/pkg/runtime/pchw/mem.c
new file mode 100644 (file)
index 0000000..99c5b49
--- /dev/null
@@ -0,0 +1,41 @@
+// 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 "malloc.h"
+
+// Assume there's an arbitrary amount of memory starting at "end".
+// Sizing PC memory is beyond the scope of this demo.
+
+void*
+SysAlloc(uintptr ask)
+{
+       static byte *p;
+       extern byte end[];
+       byte *q;
+       
+       if(p == nil) {
+               p = end;
+               p += 7 & -(uintptr)p;
+       }
+       ask += 7 & -ask;
+
+       q = p;
+       p += ask;
+       runtime·memclr(q, ask);
+       return q;
+}
+
+void
+SysFree(void *v, uintptr n)
+{
+       USED(v, n);
+}
+
+void
+SysUnused(void *v, uintptr n)
+{
+       USED(v, n);
+}
+
diff --git a/src/pkg/runtime/pchw/os.h b/src/pkg/runtime/pchw/os.h
new file mode 100644 (file)
index 0000000..5df7576
--- /dev/null
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/pkg/runtime/pchw/signals.h b/src/pkg/runtime/pchw/signals.h
new file mode 100644 (file)
index 0000000..5df7576
--- /dev/null
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/pkg/runtime/pchw/thread.c b/src/pkg/runtime/pchw/thread.c
new file mode 100644 (file)
index 0000000..634dbd5
--- /dev/null
@@ -0,0 +1,89 @@
+// 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"
+
+int8 *goos = "pchw";
+
+extern void runtime·write(int32 fd, void *v, int32 len, int32 cap);   // slice, spelled out
+
+int32
+write(int32 fd, void *v, int32 len)
+{
+       runtime·write(fd, v, len, len);
+       return len;
+}
+
+void
+minit(void)
+{
+}
+
+void
+osinit(void)
+{
+}
+
+void
+initsig(void)
+{
+}
+
+void
+exit(int32)
+{
+       for(;;);
+}
+
+// single processor, no interrupts,
+// so no need for real concurrency or atomicity
+
+void
+newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+       USED(m, g, stk, fn);
+       throw("newosproc");
+}
+
+void
+lock(Lock *l)
+{
+       if(m->locks < 0)
+               throw("lock count");
+       m->locks++;
+       if(l->key != 0)
+               throw("deadlock");
+       l->key = 1;
+}
+
+void
+unlock(Lock *l)
+{
+       m->locks--;
+       if(m->locks < 0)
+               throw("lock count");
+       if(l->key != 1)
+               throw("unlock of unlocked lock");
+       l->key = 0;
+}
+
+void
+noteclear(Note *n)
+{
+       n->lock.key = 0;
+}
+
+void
+notewakeup(Note *n)
+{
+       n->lock.key = 1;
+}
+
+void
+notesleep(Note *n)
+{
+       if(n->lock.key != 1)
+               throw("notesleep");
+}
+
index 1a547f230bfe3694a0a94b1284283c5f470d877b..ac4f45ce1e7d77c7a6fd26eeed7f731b97c3d58c 100644 (file)
@@ -46,6 +46,8 @@ walksymtab(void (*fn)(Sym*))
        // TODO(rsc): Remove once TODO at top of file is done.
        if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
                return;
+       if(goos != nil && strcmp((uint8*)goos, (uint8*)"pchw") == 0)
+               return;
 
 #ifdef __MINGW__
        v = get_symdat_addr();
@@ -251,6 +253,8 @@ splitpcln(void)
        // TODO(rsc): Remove once TODO at top of file is done.
        if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
                return;
+       if(goos != nil && strcmp((uint8*)goos, (uint8*)"pchw") == 0)
+               return;
 
        // pc/ln table bounds
 #ifdef __MINGW__