Plan9 arm64 port
As 32-bit are staying in the past, the plan9 arm64 port is back. I'm running it on bare metal, on a Pi 4. I adapted previous work from @psilva261 (https://github.com/psilva261/go-arm64.plan9). Please advice.
Previous try of including the plan9 arm64 port is here: https://github.com/golang/go/issues/57540
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 2b382a1..2b4818c 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -1811,6 +1811,7 @@
"plan9/386": false,
"plan9/amd64": false,
"plan9/arm": false,
+ "plan9/arm64": false,
"solaris/amd64": true,
"windows/386": true,
"windows/amd64": true,
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 0c9e96a..ce078ff 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -2075,6 +2075,7 @@
{0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386
{0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64
{0x00, 0x00, 0x06, 0x47}, // Plan 9 arm
+ {0x00, 0x00, 0x8c, 0x47}, // Plan 9 arm64
{0x00, 0x61, 0x73, 0x6D}, // WASM
{0x01, 0xDF}, // XCOFF 32bit
{0x01, 0xF7}, // XCOFF 64bit
diff --git a/src/cmd/go/testdata/script/work_env.txt b/src/cmd/go/testdata/script/work_env.txt
index 8b1779e..54e51da 100644
--- a/src/cmd/go/testdata/script/work_env.txt
+++ b/src/cmd/go/testdata/script/work_env.txt
@@ -1,7 +1,7 @@
go env GOWORK
stdout '^'$GOPATH'[\\/]src[\\/]go.work$'
go env
-stdout '^(set )?GOWORK=''?'$GOPATH'[\\/]src[\\/]go.work''?$'
+stdout '^(set )?GOWORK=["'']?'$GOPATH'[\\/]src[\\/]go.work["'']?$'
cd ..
go env GOWORK
diff --git a/src/cmd/internal/objfile/plan9obj.go b/src/cmd/internal/objfile/plan9obj.go
index edd4023..f9801c0 100644
--- a/src/cmd/internal/objfile/plan9obj.go
+++ b/src/cmd/internal/objfile/plan9obj.go
@@ -137,6 +137,8 @@
return "amd64"
case plan9obj.MagicARM:
return "arm"
+ case plan9obj.MagicARM64:
+ return "arm64"
}
return ""
}
diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go
index 3d35815..cc3b113 100644
--- a/src/cmd/link/internal/arm64/obj.go
+++ b/src/cmd/link/internal/arm64/obj.go
@@ -47,6 +47,9 @@
Dwarfreglr: dwarfRegLR,
TrampLimit: 0x7c00000, // 26-bit signed offset * 4, leave room for PLT etc.
+ Plan9Magic: 0x8c47,
+ Plan9_64Bit: true,
+
Adddynrel: adddynrel,
Archinit: archinit,
Archreloc: archreloc,
@@ -85,12 +88,12 @@
ld.Exitf("unknown -H option: %v", ctxt.HeadType)
case objabi.Hplan9: /* plan 9 */
- ld.HEADR = 32
+ ld.HEADR = 32 + 8
if *ld.FlagRound == -1 {
- *ld.FlagRound = 4096
+ *ld.FlagRound = 0x10000
}
if *ld.FlagTextAddr == -1 {
- *ld.FlagTextAddr = ld.Rnd(4096, *ld.FlagRound) + int64(ld.HEADR)
+ *ld.FlagTextAddr = ld.Rnd(0x10000, *ld.FlagRound) + int64(ld.HEADR)
}
case objabi.Hlinux, /* arm64 elf */
diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go
index d913953..8fee981 100644
--- a/src/cmd/link/internal/ld/main.go
+++ b/src/cmd/link/internal/ld/main.go
@@ -193,7 +193,7 @@
addstrdata1(ctxt, "runtime.buildVersion="+buildVersion)
// TODO(matloob): define these above and then check flag values here
- if ctxt.Arch.Family == sys.AMD64 && buildcfg.GOOS == "plan9" {
+ if (ctxt.Arch.Family == sys.AMD64 || ctxt.Arch.Family == sys.ARM64) && buildcfg.GOOS == "plan9" {
flag.BoolVar(&flag8, "8", false, "use 64-bit addresses in symbol table")
}
flagHeadType := flag.String("H", "", "set header `type`")
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index a0345ca..dd2a16b 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -294,7 +294,7 @@
}
l := 4
addr := ldr.SymValue(s)
- if ctxt.IsAMD64() && !flag8 {
+ if (ctxt.IsAMD64() || ctxt.IsARM64()) && !flag8 {
ctxt.Out.Write32b(uint32(addr >> 32))
l = 8
}
diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/asm_plan9_arm64.s b/src/cmd/vendor/golang.org/x/sys/plan9/asm_plan9_arm64.s
new file mode 100644
index 0000000..9014318
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/plan9/asm_plan9_arm64.s
@@ -0,0 +1,28 @@
+// Copyright 2009 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 "textflag.h"
+
+// System call support for plan9 on arm64
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-64
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-88
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-56
+ JMP syscall·seek(SB)
+
+TEXT ·exit(SB),NOSPLIT,$8-8
+ JMP syscall·exit(SB)
diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm64.go b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm64.go
new file mode 100644
index 0000000..dd0265a
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm64.go
@@ -0,0 +1,286 @@
+// go run mksyscall.go -l32 -plan9 -tags plan9,arm64 syscall_plan9.go
+// Code generated by the command above; DO NOT EDIT.
+
+//go:build plan9 && arm64
+// +build plan9,arm64
+
+package plan9
+
+import "unsafe"
+
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fd2path(fd int, buf []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]int32) (err error) {
+ r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func await(s []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(s) > 0 {
+ _p0 = unsafe.Pointer(&s[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func open(path string, mode int) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func create(path string, mode int, perm uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func remove(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, edir []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(name string, old string, flag int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(name)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(fd int, afd int, old string, flag int, aname string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(aname)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wstat(path string, edir []byte) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func chdir(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int, newfd int) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+ r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, edir []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fwstat(fd int, edir []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go
index d202d50..3ceb23c 100644
--- a/src/debug/buildinfo/buildinfo.go
+++ b/src/debug/buildinfo/buildinfo.go
@@ -274,7 +274,7 @@
if len(magic) >= 4 {
m := binary.BigEndian.Uint32(magic)
switch m {
- case plan9obj.Magic386, plan9obj.MagicAMD64, plan9obj.MagicARM:
+ case plan9obj.Magic386, plan9obj.MagicAMD64, plan9obj.MagicARM, plan9obj.MagicARM64:
return true
}
}
diff --git a/src/debug/plan9obj/file.go b/src/debug/plan9obj/file.go
index 0880c3c..d89c6cd 100644
--- a/src/debug/plan9obj/file.go
+++ b/src/debug/plan9obj/file.go
@@ -130,7 +130,7 @@
func parseMagic(magic []byte) (uint32, error) {
m := binary.BigEndian.Uint32(magic)
switch m {
- case Magic386, MagicAMD64, MagicARM:
+ case Magic386, MagicAMD64, MagicARM, MagicARM64:
return m, nil
}
return 0, &formatError{0, "bad magic number", magic}
@@ -145,7 +145,7 @@
if _, err := r.ReadAt(magic[:], 0); err != nil {
return nil, err
}
- _, err := parseMagic(magic[:])
+ m, err := parseMagic(magic[:])
if err != nil {
return nil, err
}
@@ -169,7 +169,11 @@
return nil, err
}
f.PtrSize = 8
- f.LoadAddress = 0x200000
+ if m == MagicARM64 {
+ f.LoadAddress = 0x10000
+ } else {
+ f.LoadAddress = 0x200000
+ }
f.HdrSize += 8
}
diff --git a/src/debug/plan9obj/file_test.go b/src/debug/plan9obj/file_test.go
index 7e107bc..75498fc 100644
--- a/src/debug/plan9obj/file_test.go
+++ b/src/debug/plan9obj/file_test.go
@@ -38,6 +38,17 @@
{"pcsz", 0xca0, 0x7947},
},
},
+ {
+ "testdata/arm64-plan9-exec",
+ FileHeader{MagicARM64, 0x408, 0x1003c, 8, 0x10000, 40},
+ []*SectionHeader{
+ {"text", 0x4a00, 0x28},
+ {"data", 0xaa0, 0x4a28},
+ {"syms", 0x294a, 0x54c8},
+ {"spsz", 0x0, 0x7e12},
+ {"pcsz", 0xa6c, 0x7e12},
+ },
+ },
}
func TestOpen(t *testing.T) {
diff --git a/src/debug/plan9obj/plan9obj.go b/src/debug/plan9obj/plan9obj.go
index 7a19451..98e97a2 100644
--- a/src/debug/plan9obj/plan9obj.go
+++ b/src/debug/plan9obj/plan9obj.go
@@ -33,4 +33,5 @@
Magic386 = (4*11+0)*11 + 7
MagicAMD64 = (4*26+0)*26 + 7 + Magic64
MagicARM = (4*20+0)*20 + 7
+ MagicARM64 = (4*28+0)*28 + 7 + Magic64
)
diff --git a/src/debug/plan9obj/testdata/arm64-plan9-exec b/src/debug/plan9obj/testdata/arm64-plan9-exec
new file mode 100755
index 0000000..3fa2c42
--- /dev/null
+++ b/src/debug/plan9obj/testdata/arm64-plan9-exec
Binary files differ
diff --git a/src/internal/platform/zosarch.go b/src/internal/platform/zosarch.go
index a2f5b22..a81735c 100644
--- a/src/internal/platform/zosarch.go
+++ b/src/internal/platform/zosarch.go
@@ -53,6 +53,7 @@
{"plan9", "386"},
{"plan9", "amd64"},
{"plan9", "arm"},
+ {"plan9", "arm64"},
{"solaris", "amd64"},
{"wasip1", "wasm"},
{"windows", "386"},
@@ -106,6 +107,7 @@
{"plan9", "386"}: {},
{"plan9", "amd64"}: {},
{"plan9", "arm"}: {},
+ {"plan9", "arm64"}: {},
{"solaris", "amd64"}: {CgoSupported: true},
{"wasip1", "wasm"}: {},
{"windows", "386"}: {CgoSupported: true, FirstClass: true},
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index 4a16ba0..361beb1 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -4562,7 +4562,11 @@
if err != nil {
// Try to deflake spurious "connection reset by peer" under load.
// See golang.org/issue/22540.
- time.Sleep(10 * time.Millisecond)
+ deflake := 10 * time.Millisecond
+ if runtime.GOOS == "plan9" {
+ deflake = 100 * time.Millisecond
+ }
+ time.Sleep(deflake)
res, err = cst.c.Get(cst.ts.URL)
if err != nil {
t.Error(err)
diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go
index a79e9f8..a0cedb7 100644
--- a/src/net/udpsock_test.go
+++ b/src/net/udpsock_test.go
@@ -679,7 +679,7 @@
}
switch runtime.GOOS {
- case "dragonfly", "openbsd":
+ case "dragonfly", "openbsd", "plan9":
// DragonflyBSD's IPv6 sockets are always IPv6-only, according to the man page:
// https://www.dragonflybsd.org/cgi/web-man?command=ip6 (search for IPV6_V6ONLY).
// OpenBSD's IPv6 sockets are always IPv6-only, according to the man page:
diff --git a/src/runtime/defs_plan9_arm64.go b/src/runtime/defs_plan9_arm64.go
new file mode 100644
index 0000000..e6803c9
--- /dev/null
+++ b/src/runtime/defs_plan9_arm64.go
@@ -0,0 +1,103 @@
+// Copyright 2015 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.
+
+package runtime
+
+const _PAGESHIFT = 16
+const _PAGESIZE = 1 << _PAGESHIFT
+
+type ureg struct {
+ /* AArch64 registers */
+ r0 uint64 /* general registers */
+ r1 uint64 /* ... */
+ r2 uint64 /* ... */
+ r3 uint64 /* ... */
+ r4 uint64 /* ... */
+ r5 uint64 /* ... */
+ r6 uint64 /* ... */
+ r7 uint64 /* ... */
+ r8 uint64 /* ... */
+ r9 uint64 /* ... */
+ r10 uint64 /* ... */
+ r11 uint64 /* ... */
+ r12 uint64 /* ... */
+ r13 uint64 /* ... */
+ r14 uint64 /* ... */
+ r15 uint64 /* ... */
+ r16 uint64 /* ... */
+ r17 uint64 /* ... */
+ r18 uint64 /* ... */
+ r19 uint64 /* ... */
+ r20 uint64 /* ... */
+ r21 uint64 /* ... */
+ r22 uint64 /* ... */
+ r23 uint64 /* ... */
+ r24 uint64 /* ... */
+ r25 uint64 /* ... */
+ r26 uint64 /* ... */
+ r27 uint64 /* ... */
+ r28 uint64 /* ... */
+ r29 uint64 /* ... */
+ r30 uint64 /* link (lr) */
+ sp uint64
+ pc uint64 /* interrupted addr */
+ psr uint64
+ typ uint64 /* of exception */
+}
+
+type sigctxt struct {
+ u *ureg
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func (c *sigctxt) pc() uintptr { return uintptr(c.u.pc) }
+
+func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) }
+func (c *sigctxt) lr() uintptr { return uintptr(c.u.r30) }
+
+func (c *sigctxt) setpc(x uintptr) { c.u.pc = uint64(x) }
+func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint64(x) }
+func (c *sigctxt) setlr(x uintptr) { c.u.r30 = uint64(x) }
+func (c *sigctxt) savelr(x uintptr) { c.u.r0 = uint64(x) }
+
+func dumpregs(u *ureg) {
+ print("r0 ", hex(u.r0), "\n")
+ print("r1 ", hex(u.r1), "\n")
+ print("r2 ", hex(u.r2), "\n")
+ print("r3 ", hex(u.r3), "\n")
+ print("r4 ", hex(u.r4), "\n")
+ print("r5 ", hex(u.r5), "\n")
+ print("r6 ", hex(u.r6), "\n")
+ print("r7 ", hex(u.r7), "\n")
+ print("r8 ", hex(u.r8), "\n")
+ print("r9 ", hex(u.r9), "\n")
+ print("r10 ", hex(u.r10), "\n")
+ print("r11 ", hex(u.r11), "\n")
+ print("r12 ", hex(u.r12), "\n")
+ print("r13 ", hex(u.r13), "\n")
+ print("r14 ", hex(u.r14), "\n")
+ print("r15 ", hex(u.r15), "\n")
+ print("r16 ", hex(u.r16), "\n")
+ print("r17 ", hex(u.r17), "\n")
+ print("r18 ", hex(u.r18), "\n")
+ print("r19 ", hex(u.r19), "\n")
+ print("r20 ", hex(u.r20), "\n")
+ print("r21 ", hex(u.r21), "\n")
+ print("r22 ", hex(u.r22), "\n")
+ print("r23 ", hex(u.r23), "\n")
+ print("r24 ", hex(u.r24), "\n")
+ print("r25 ", hex(u.r25), "\n")
+ print("r26 ", hex(u.r26), "\n")
+ print("r27 ", hex(u.r27), "\n")
+ print("r28 ", hex(u.r28), "\n")
+ print("r29 ", hex(u.r29), "\n")
+ print("r30 ", hex(u.r30), "\n")
+ print("sp ", hex(u.sp), "\n")
+ print("pc ", hex(u.pc), "\n")
+ print("psr ", hex(u.psr), "\n")
+ print("type ", hex(u.typ), "\n")
+}
+
+func sigpanictramp()
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
index 80c101f..f738101 100644
--- a/src/runtime/os_plan9.go
+++ b/src/runtime/os_plan9.go
@@ -587,10 +587,3 @@
// fall back to unix time
return int64(frombe(t[0]))
}
-
-//go:nosplit
-func walltime() (sec int64, nsec int32) {
- var t [1]uint64
- readtime(&t[0], 1, 1)
- return timesplit(frombe(t[0]))
-}
diff --git a/src/runtime/os_plan9_386.go b/src/runtime/os_plan9_386.go
new file mode 100644
index 0000000..66f09f4
--- /dev/null
+++ b/src/runtime/os_plan9_386.go
@@ -0,0 +1,12 @@
+// Copyright 2025 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.
+
+package runtime
+
+//go:nosplit
+func walltime() (sec int64, nsec int32) {
+ var t [1]uint64
+ readtime(&t[0], 1, 1)
+ return timesplit(frombe(t[0]))
+}
diff --git a/src/runtime/os_plan9_amd64.go b/src/runtime/os_plan9_amd64.go
new file mode 100644
index 0000000..66f09f4
--- /dev/null
+++ b/src/runtime/os_plan9_amd64.go
@@ -0,0 +1,12 @@
+// Copyright 2025 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.
+
+package runtime
+
+//go:nosplit
+func walltime() (sec int64, nsec int32) {
+ var t [1]uint64
+ readtime(&t[0], 1, 1)
+ return timesplit(frombe(t[0]))
+}
diff --git a/src/runtime/os_plan9_arm.go b/src/runtime/os_plan9_arm.go
index cce6229..2e9530e 100644
--- a/src/runtime/os_plan9_arm.go
+++ b/src/runtime/os_plan9_arm.go
@@ -13,3 +13,10 @@
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
return nanotime()
}
+
+//go:nosplit
+func walltime() (sec int64, nsec int32) {
+ var t [1]uint64
+ readtime(&t[0], 1, 1)
+ return timesplit(frombe(t[0]))
+}
diff --git a/src/runtime/os_plan9_arm64.go b/src/runtime/os_plan9_arm64.go
new file mode 100644
index 0000000..3d3dd7e
--- /dev/null
+++ b/src/runtime/os_plan9_arm64.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+package runtime
+
+//go:nosplit
+func cputicks() int64 {
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
+ // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ return nanotime()
+}
diff --git a/src/runtime/rt0_plan9_arm64.s b/src/runtime/rt0_plan9_arm64.s
new file mode 100644
index 0000000..192ff38
--- /dev/null
+++ b/src/runtime/rt0_plan9_arm64.s
@@ -0,0 +1,16 @@
+// Copyright 2015 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 "textflag.h"
+
+//in plan 9 argc is at top of stack followed by ptrs to arguments
+
+TEXT _rt0_arm64_plan9(SB),NOSPLIT|NOFRAME,$0
+ MOVD R0, _tos(SB)
+ MOVD 0(RSP), R0
+ MOVD $8(RSP), R1
+ MOVD $runtime·rt0_go(SB), R2
+ BL (R2)
+
+GLOBL _tos(SB), NOPTR, $8
diff --git a/src/runtime/sys_plan9_arm64.s b/src/runtime/sys_plan9_arm64.s
new file mode 100644
index 0000000..f4d3a25
--- /dev/null
+++ b/src/runtime/sys_plan9_arm64.s
@@ -0,0 +1,298 @@
+// Copyright 2015 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 "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+// from ../syscall/zsysnum_plan9.go
+
+#define SYS_SYSR1 0
+#define SYS_BIND 2
+#define SYS_CHDIR 3
+#define SYS_CLOSE 4
+#define SYS_DUP 5
+#define SYS_ALARM 6
+#define SYS_EXEC 7
+#define SYS_EXITS 8
+#define SYS_FAUTH 10
+#define SYS_SEGBRK 12
+#define SYS_OPEN 14
+#define SYS_OSEEK 16
+#define SYS_SLEEP 17
+#define SYS_RFORK 19
+#define SYS_PIPE 21
+#define SYS_CREATE 22
+#define SYS_FD2PATH 23
+#define SYS_BRK_ 24
+#define SYS_REMOVE 25
+#define SYS_NOTIFY 28
+#define SYS_NOTED 29
+#define SYS_SEGATTACH 30
+#define SYS_SEGDETACH 31
+#define SYS_SEGFREE 32
+#define SYS_SEGFLUSH 33
+#define SYS_RENDEZVOUS 34
+#define SYS_UNMOUNT 35
+#define SYS_SEMACQUIRE 37
+#define SYS_SEMRELEASE 38
+#define SYS_SEEK 39
+#define SYS_FVERSION 40
+#define SYS_ERRSTR 41
+#define SYS_STAT 42
+#define SYS_FSTAT 43
+#define SYS_WSTAT 44
+#define SYS_FWSTAT 45
+#define SYS_MOUNT 46
+#define SYS_AWAIT 47
+#define SYS_PREAD 50
+#define SYS_PWRITE 51
+#define SYS_TSEMACQUIRE 52
+#define SYS_NSEC 53
+
+//func open(name *byte, mode int, perm int32) int
+TEXT runtime·open(SB),NOSPLIT,$0-20
+ MOVD $SYS_OPEN, R0
+ SVC $0
+ MOVWU R0, ret+16(FP)
+ RET
+
+//func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+TEXT runtime·pread(SB),NOSPLIT,$0-36
+ MOVD $SYS_PREAD, R0
+ SVC $0
+ MOVWU R0, ret+32(FP)
+ RET
+
+//func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+TEXT runtime·pwrite(SB),NOSPLIT,$0-36
+ MOVD $SYS_PWRITE, R0
+ SVC $0
+ MOVWU R0, ret+32(FP)
+ RET
+
+//func seek(fd int32, offset int64, whence int32) int64
+TEXT runtime·seek(SB),NOSPLIT,$0-32
+ MOVD $ret+24(FP), R0
+ MOVWU fd+0(FP), R2
+ MOVD offset+8(FP), R3
+ MOVWU whence+16(FP), R4
+
+ MOVD $sysargs-0(SP), R1
+
+ MOVD R0, 8(R1)
+ MOVWU R2, 16(R1)
+ MOVD R3, 24(R1)
+ MOVWU R4, 32(R1)
+
+ MOVD $SYS_SEEK, R0
+ SVC $0
+
+ CMP $-1, R0
+ BNE 2(PC)
+ MOVD R0, ret+24(FP)
+ RET
+
+//func closefd(fd int32) int32
+TEXT runtime·closefd(SB),NOSPLIT,$0-12
+ MOVD $SYS_CLOSE, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func dupfd(old, new int32) int32
+TEXT runtime·dupfd(SB),NOSPLIT,$0-12
+ MOVD $SYS_DUP, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func exits(msg *byte)
+TEXT runtime·exits(SB),NOSPLIT,$0-8
+ MOVD $SYS_EXITS, R0
+ SVC $0
+ RET
+
+//func brk_(addr unsafe.Pointer) int32
+TEXT runtime·brk_(SB),NOSPLIT,$0-12
+ MOVD $SYS_BRK_, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func sleep(ms int32) int32
+TEXT runtime·sleep(SB),NOSPLIT,$0-12
+ MOVD $SYS_SLEEP, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func plan9_semacquire(addr *uint32, block int32) int32
+TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0-20
+ MOVD $SYS_SEMACQUIRE, R0
+ SVC $0
+ MOVWU R0, ret+16(FP)
+ RET
+
+//func plan9_tsemacquire(addr *uint32, ms int32) int32
+TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-20
+ MOVD $SYS_TSEMACQUIRE, R0
+ SVC $0
+ MOVWU R0, ret+16(FP)
+ RET
+
+// func timesplit(u uint64) (sec int64, nsec int32)
+TEXT runtime·timesplit(SB),NOSPLIT,$0-16
+ // load u (nanoseconds)
+ MOVD u+0(FP), R0
+
+ // compute sec = u / 1e9
+ MOVD R0, R1
+ MOVD $1000000000, R2
+ UDIV R2, R1 // R1 = R1 / R2 -> seconds
+
+ // compute rem = u - sec * 1e9
+ MOVD R1, R3
+ MUL R3, R2 // R2 = sec * 1e9
+ SUB R2, R0 // R0 = u - (sec*1e9) -> remainder (nsec)
+
+ // store results
+ MOVD R1, sec+0(FP)
+ MOVWU R0, nsec+8(FP)
+ RET
+
+//func nsec(*int64) int64
+TEXT runtime·nsec(SB),NOSPLIT|NOFRAME,$0-16
+ MOVD $SYS_NSEC, R0
+ SVC $0
+ MOVD R0, ret+8(FP)
+ RET
+
+// func walltime() (sec int64, nsec int32)
+TEXT runtime·walltime(SB),NOSPLIT,$16-12
+ // use nsec system call to get current time in nanoseconds
+
+ MOVD $SYS_NSEC, R0
+ SVC $0
+
+ MOVD R0, R1
+ MOVD $1000000000, R2
+ UDIV R2, R1
+
+ MOVD R1, R3
+ MUL R3, R2
+ SUB R2, R0
+
+ MOVD R1,sec+0(FP)
+ MOVWU R0,nsec+8(FP)
+ RET
+
+//func notify(fn unsafe.Pointer) int32
+TEXT runtime·notify(SB),NOSPLIT,$0-12
+ MOVD $SYS_NOTIFY, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func noted(mode int32) int32
+TEXT runtime·noted(SB),NOSPLIT,$0-12
+ MOVD $SYS_NOTED, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func plan9_semrelease(addr *uint32, count int32) int32
+TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0-20
+ MOVD $SYS_SEMRELEASE, R0
+ SVC $0
+ MOVWU R0, ret+16(FP)
+ RET
+
+//func rfork(flags int32) int32
+TEXT runtime·rfork(SB),NOSPLIT,$0-12
+ MOVD $SYS_RFORK, R0
+ SVC $0
+ MOVWU R0, ret+8(FP)
+ RET
+
+//func tstart_plan9(newm *m)
+TEXT runtime·tstart_plan9(SB),NOSPLIT,$8-8
+ MOVD newm+0(FP), R1
+ MOVD m_g0(R1), g
+
+ // Layout new m scheduler stack on os stack.
+ MOVD RSP, R0
+ MOVD R0, g_stack+stack_hi(g)
+ SUB $(64*1024), R0
+ MOVD R0, (g_stack+stack_lo)(g)
+ MOVD R0, g_stackguard0(g)
+ MOVD R0, g_stackguard1(g)
+
+ // Initialize procid from TOS struct.
+ MOVD _tos(SB), R0
+ MOVWU 64(R0), R0
+ MOVD R0, m_procid(R1) // save pid as m->procid
+
+ BL runtime·mstart(SB)
+
+ // Exit the thread.
+ MOVD $0, R0
+ MOVD R0, 8(RSP)
+ CALL runtime·exits(SB)
+ JMP 0(PC)
+
+//func sigtramp(ureg, note unsafe.Pointer)
+TEXT runtime·sigtramp(SB),NOSPLIT,$0-16
+ // check that g and m exist
+ CMP $0, g
+ BEQ 4(PC)
+ MOVD g_m(g), R0
+ CMP $0, R0
+ BNE 2(PC)
+ BL runtime·badsignal2(SB) // will exit
+
+ // save args
+ MOVD ureg+0(FP), R1
+ MOVD note+8(FP), R2
+
+ // change stack
+ MOVD m_gsignal(R0), R3
+ MOVD (g_stack+stack_hi)(R3), R4
+ MOVD R4, RSP
+
+ // make room for args, retval and g
+ SUB $48, RSP
+
+ // save g
+ MOVD g, R3
+ MOVD R3, 40(RSP)
+
+ // g = m->gsignal
+ MOVD m_gsignal(R0), g
+
+ // load args and call sighandler
+ MOVD R1, 8(RSP)
+ MOVD R2, 16(RSP)
+ MOVD R3, 24(RSP)
+
+ BL runtime·sighandler(SB)
+ MOVWU 32(RSP), R0 // retval
+
+ // restore g
+ MOVD 40(RSP), g
+
+ // call noted(R0)
+ MOVD R0, 8(RSP)
+ BL runtime·noted(SB)
+ RET
+
+//func sigpanictramp()
+TEXT runtime·sigpanictramp(SB),NOSPLIT,$0-0
+ MOVD.W R0, -16(RSP)
+ B runtime·sigpanic(SB)
+
+//func setfpmasks()
+// Mask all SSE floating-point exceptions (only amd64?)
+TEXT runtime·setfpmasks(SB),NOSPLIT,$0
+ RET
diff --git a/src/runtime/tls_arm64.h b/src/runtime/tls_arm64.h
index 3aa8c63..afa6cf6 100644
--- a/src/runtime/tls_arm64.h
+++ b/src/runtime/tls_arm64.h
@@ -36,6 +36,10 @@
#define MRS_TPIDR_R0 WORD $0xd53bd040 // MRS TPIDR_EL0, R0
#endif
+#ifdef GOOS_plan9
+#define MRS_TPIDR_R0 WORD $0xd53bd040 // MRS TPIDR_EL0, R0
+#endif
+
#ifdef GOOS_windows
#define TLS_windows
#endif
diff --git a/src/syscall/asm_plan9_arm64.s b/src/syscall/asm_plan9_arm64.s
new file mode 100644
index 0000000..6605fb4
--- /dev/null
+++ b/src/syscall/asm_plan9_arm64.s
@@ -0,0 +1,216 @@
+// Copyright 2009 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 "textflag.h"
+#include "funcdata.h"
+
+#define SYS_ERRSTR 41 /* from zsysnum_plan9.go */
+#define SYS_SEEK 39 /* from zsysnum_plan9.go */
+
+// System call support for plan9 on arm64
+
+//func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
+TEXT ·Syscall(SB),NOSPLIT,$168-64
+ NO_LOCAL_POINTERS
+ BL runtime·entersyscall(SB)
+
+ MOVD trap+0(FP), R0
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+
+ // move to syscall args
+ MOVD R2, sysargs-192(FP)
+ MOVD R3, sysargs-184(FP)
+ MOVD R4, sysargs-176(FP)
+
+ SVC $0
+
+ // put return values into r1, r2, err
+ MOVD R0, r1+32(FP)
+ MOVD R1, r2+40(FP)
+ MOVD ZR, err+48(FP)
+
+ // put error if needed
+ CMP $-1, R0
+ BEQ syscallerr
+ BL runtime·exitsyscall(SB)
+ MOVD $·emptystring+0(SB), R2
+ B syscallok
+syscallerr:
+ MOVD $errbuf-128(SP), R2
+ MOVD $128, R3
+
+ MOVD $SYS_ERRSTR, R0
+ MOVD R2, err-192(FP)
+ MOVD R3, nerr-184(FP)
+ SVC $0
+
+ BL runtime·exitsyscall(SB)
+ BL runtime·gostring(SB)
+ MOVD $str-160(SP), R2
+syscallok:
+ MOVD $err+48(FP), R1
+ MOVD 0(R2), R3
+ MOVD 8(R2), R4
+ MOVD R3, 0(R1)
+ MOVD R4, 8(R1)
+ RET
+
+
+//func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
+// Actually Syscall5 but the rest of the code expects it to be named Syscall6.
+TEXT ·Syscall6(SB),NOSPLIT,$168-88
+ NO_LOCAL_POINTERS
+ BL runtime·entersyscall(SB)
+
+ MOVD trap+0(FP), R1
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+ MOVD a4+32(FP), R5
+ MOVD a5+40(FP), R6
+ MOVD a6+48(FP), R7
+
+ // dereference pointers
+ MOVD R1, R0
+ MOVD R2, sysargs-192(FP)
+ MOVD R3, sysargs-184(FP)
+ MOVD R4, sysargs-176(FP)
+ MOVD R5, sysargs-168(FP)
+ MOVD R6, sysargs-160(FP)
+ MOVD R7, sysargs-152(FP)
+
+ SVC $0
+
+ // put return value into r1, r2, err
+ MOVD R0, r1+56(FP)
+ MOVD R1, r2+64(FP)
+ MOVD ZR, err+72(FP)
+
+ // put error if needed
+ CMP $-1, R0
+ BEQ syscall6err
+ BL runtime·exitsyscall(SB)
+ MOVD $·emptystring+0(SB), R2
+ B syscall6ok
+syscall6err:
+ MOVD $errbuf-128(SP), R2
+ MOVD $128, R3
+
+ MOVD $SYS_ERRSTR, R0
+ MOVD R2, err-192(FP)
+ MOVD R3, nerr-184(FP)
+ SVC $0
+
+ BL runtime·exitsyscall(SB)
+ BL runtime·gostring(SB)
+ MOVD $str-160(SP), R2
+syscall6ok:
+ MOVD $err+72(FP), R1
+ MOVD 0(R2), R3
+ MOVD 8(R2), R4
+ MOVD R3, 0(R1)
+ MOVD R4, 8(R1)
+ RET
+
+//func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+TEXT ·RawSyscall(SB),NOSPLIT,$24-56
+ MOVD trap+0(FP), R1
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+
+ // move to syscall args
+ MOVD R1, R0
+ MOVD R2, sysargs-48(FP)
+ MOVD R3, sysargs-40(FP)
+ MOVD R4, sysargs-32(FP)
+
+ SVC $0
+
+ // put return values into r1, r2, err
+ MOVD R0, r1+32(FP)
+ MOVD R0, r2+40(FP)
+ MOVD R0, err+48(FP)
+
+ RET
+
+//func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+// Actually RawSyscall5 but the rest of the code expects it to be named RawSyscall6.
+TEXT ·RawSyscall6(SB),NOSPLIT,$48-80
+ MOVD trap+0(FP), R1
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+ MOVD a4+32(FP), R5
+ MOVD a5+40(FP), R6
+ MOVD a6+48(FP), R7
+
+ // move to syscall args
+ MOVD R1, R0
+ MOVD R2, sysargs-64(FP)
+ MOVD R3, sysargs-56(FP)
+ MOVD R4, sysargs-48(FP)
+ MOVD R5, sysargs-40(FP)
+ MOVD R6, sysargs-32(FP)
+ MOVD R7, sysargs-24(FP)
+
+ SVC $0
+
+ // put return values into r1, r2, err
+ MOVD R0, r1+56(FP)
+ MOVD R1, r2+64(FP)
+ MOVD ZR, err+72(FP)
+
+ RET
+
+//func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+TEXT ·seek(SB),NOSPLIT,$168-56
+ NO_LOCAL_POINTERS
+
+ MOVD $newoffset+32(FP), R0
+ MOVWU fd+8(FP), R2
+ MOVD offset+16(FP), R3
+ MOVWU whence+24(FP), R4
+
+ // move to syscall args
+ MOVD R0, sysargs-192(FP)
+ MOVWU R2, sysargs-184(FP)
+ MOVD R3, sysargs-176(FP)
+ MOVWU R4, sysargs-168(FP)
+
+ MOVD $SYS_SEEK, R0
+ SVC $0
+
+ // put err
+ MOVD ZR, err+40(FP)
+
+ // put error if needed
+ CMP $-1, R0
+ BEQ syscallerr
+ MOVD $·emptystring+0(SB), R2
+ B syscallok
+syscallerr:
+ MOVD R0, newoffset+32(FP)
+
+ MOVD $errbuf-128(SP), R2
+ MOVD $128, R3
+
+ MOVD $SYS_ERRSTR, R0
+ MOVD R2, err-192(FP)
+ MOVD R3, nerr-184(FP)
+ SVC $0
+
+ BL runtime·gostring(SB)
+ MOVD $str-160(SP), R2
+syscallok:
+ MOVD $err+40(FP), R1
+ MOVD 0(R2), R3
+ MOVD 8(R2), R4
+ MOVD R3, 0(R1)
+ MOVD R4, 8(R1)
+ RET
+
+
diff --git a/src/syscall/zsyscall_plan9_arm64.go b/src/syscall/zsyscall_plan9_arm64.go
new file mode 100644
index 0000000..2be5bd9
--- /dev/null
+++ b/src/syscall/zsyscall_plan9_arm64.go
@@ -0,0 +1,284 @@
+// mksyscall.pl -l32 -plan9 -tags plan9,arm64 syscall_plan9.go
+// Code generated by the command above; DO NOT EDIT.
+
+//go:build plan9 && arm64
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fd2path(fd int, buf []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]int32) (err error) {
+ r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func await(s []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(s) > 0 {
+ _p0 = unsafe.Pointer(&s[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func open(path string, mode int) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func create(path string, mode int, perm uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func remove(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, edir []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(name string, old string, flag int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(name)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(fd int, afd int, old string, flag int, aname string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(aname)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wstat(path string, edir []byte) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func chdir(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int, newfd int) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+ r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, edir []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fwstat(fd int, edir []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I spotted some possible problems with your PR:
1. The commit title should start with the primary affected package name followed by a colon, like "net/http: improve [...]".
2. The first word in the commit title after the package should be a lowercase English word (usually a verb).
3. You usually need to reference a bug number for all but trivial or cosmetic fixes. For this repo, the format is usually 'Fixes #12345' or 'Updates #12345' at the end of the commit message. Should you have a bug reference?
Please address any problems by updating the GitHub PR.
When complete, mark this comment as 'Done' and click the [blue 'Reply' button](https://go.dev/wiki/GerritBot#i-left-a-reply-to-a-comment-in-gerrit-but-no-one-but-me-can-see-it) above. These findings are based on heuristics; if a finding does not apply, briefly reply here saying so.
To update the commit title or commit message body shown here in Gerrit, you must edit the GitHub PR title and PR description (the first comment) in the GitHub web interface using the 'Edit' button or 'Edit' menu entry there. Note: pushing a new commit to the PR will not automatically update the commit message used by Gerrit.
For more details, see:
(In general for Gerrit code reviews, the change author is expected to [log in to Gerrit](https://go-review.googlesource.com/login/) with a Gmail or other Google account and then close out each piece of feedback by marking it as 'Done' if implemented as suggested or otherwise reply to each review comment. See the [Review](https://go.dev/doc/contribute#review) section of the Contributing Guide for details.)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Congratulations on opening your first change. Thank you for your contribution!
Next steps:
A maintainer will review your change and provide feedback. See
https://go.dev/doc/contribute#review for more info and tips to get your
patch through code review.
Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.
During May-July and Nov-Jan the Go project is in a code freeze, during which
little code gets reviewed or merged. If a reviewer responds with a comment like
R=go1.11 or adds a tag like "wait-release", it means that this CL will be
reviewed as part of the next development cycle. See https://go.dev/s/release
for more details.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Hold | +1 |
Previous try of including the plan9 arm64 port is here: https://github.com/golang/go/issues/57540Note that this proposal was declined. You will need to open a new proposal if you believe things have changed. It is nice that the total diff is quite small.
If you haven't seen it already, also take a look through https://go.dev/wiki/PortingPolicy for the general port requirements.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Previous try of including the plan9 arm64 port is here: https://github.com/golang/go/issues/57540Note that this proposal was declined. You will need to open a new proposal if you believe things have changed. It is nice that the total diff is quite small.
If you haven't seen it already, also take a look through https://go.dev/wiki/PortingPolicy for the general port requirements.
Thanks Michael. I'll read.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Previous try of including the plan9 arm64 port is here: https://github.com/golang/go/issues/57540Rafael DinizNote that this proposal was declined. You will need to open a new proposal if you believe things have changed. It is nice that the total diff is quite small.
If you haven't seen it already, also take a look through https://go.dev/wiki/PortingPolicy for the general port requirements.
Thanks Michael. I'll read.
Just to clarify, I opened a proposal, which was promptly rejected:
https://github.com/golang/go/issues/76272
Should I open a new proposal or ask to re-open the one I opened, in order a discussion can actually happen?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I think you have an ABI clash between the go arm64 compiler and the 9front syscall interface regarding alignment of arguments. For example `dupfd` has two int32 arguments. The go compiler packs these together onto the stack with 4-byte alignment, but the 9front syscall entry expects them each aligned to 8 bytes. Therefore the `dupfd(bintimeFD, 18)` call from `osinit` creates the wrong file descriptor, causing the `readtime` function to fail and prevent the go runtime from initialising.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I think you have an ABI clash between the go arm64 compiler and the 9front syscall interface regarding alignment of arguments. For example `dupfd` has two int32 arguments. The go compiler packs these together onto the stack with 4-byte alignment, but the 9front syscall entry expects them each aligned to 8 bytes. Therefore the `dupfd(bintimeFD, 18)` call from `osinit` creates the wrong file descriptor, causing the `readtime` function to fail and prevent the go runtime from initialising.
Note that this comment applies specifically to the functions in `runtime/sys_plan9_arm64.s`.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I spotted some possible problems with your PR:
1. The commit title should start with the primary affected package name followed by a colon, like "net/http: improve [...]".
2. The first word in the commit title after the package should be a lowercase English word (usually a verb).
3. You usually need to reference a bug number for all but trivial or cosmetic fixes. For this repo, the format is usually 'Fixes #12345' or 'Updates #12345' at the end of the commit message. Should you have a bug reference?Please address any problems by updating the GitHub PR.
When complete, mark this comment as 'Done' and click the [blue 'Reply' button](https://go.dev/wiki/GerritBot#i-left-a-reply-to-a-comment-in-gerrit-but-no-one-but-me-can-see-it) above. These findings are based on heuristics; if a finding does not apply, briefly reply here saying so.
To update the commit title or commit message body shown here in Gerrit, you must edit the GitHub PR title and PR description (the first comment) in the GitHub web interface using the 'Edit' button or 'Edit' menu entry there. Note: pushing a new commit to the PR will not automatically update the commit message used by Gerrit.
For more details, see:
- [how to update commit messages](https://go.dev/wiki/GerritBot/#how-does-gerritbot-determine-the-final-commit-message) for PRs imported into Gerrit.
- the Go project's [conventions for commit messages](https://go.dev/doc/contribute#commit_messages) that you should follow.
(In general for Gerrit code reviews, the change author is expected to [log in to Gerrit](https://go-review.googlesource.com/login/) with a Gmail or other Google account and then close out each piece of feedback by marking it as 'Done' if implemented as suggested or otherwise reply to each review comment. See the [Review](https://go.dev/doc/contribute#review) section of the Contributing Guide for details.)
Should I squash the commits to a single commit and or keep this MR with fine-grained commits, one commit per package (more or less how it is right now)? I'll edit the commit messages in any case.
Richard MillerI think you have an ABI clash between the go arm64 compiler and the 9front syscall interface regarding alignment of arguments. For example `dupfd` has two int32 arguments. The go compiler packs these together onto the stack with 4-byte alignment, but the 9front syscall entry expects them each aligned to 8 bytes. Therefore the `dupfd(bintimeFD, 18)` call from `osinit` creates the wrong file descriptor, causing the `readtime` function to fail and prevent the go runtime from initialising.
Note that this comment applies specifically to the functions in `runtime/sys_plan9_arm64.s`.
Thanks for finding looking at this Richard! I'm working on it.
Previous try of including the plan9 arm64 port is here: https://github.com/golang/go/issues/57540Rafael DinizNote that this proposal was declined. You will need to open a new proposal if you believe things have changed. It is nice that the total diff is quite small.
If you haven't seen it already, also take a look through https://go.dev/wiki/PortingPolicy for the general port requirements.
Rafael DinizThanks Michael. I'll read.
Just to clarify, I opened a proposal, which was promptly rejected:
https://github.com/golang/go/issues/76272
Should I open a new proposal or ask to re-open the one I opened, in order a discussion can actually happen?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Rafael DinizI spotted some possible problems with your PR:
1. The commit title should start with the primary affected package name followed by a colon, like "net/http: improve [...]".
2. The first word in the commit title after the package should be a lowercase English word (usually a verb).
3. You usually need to reference a bug number for all but trivial or cosmetic fixes. For this repo, the format is usually 'Fixes #12345' or 'Updates #12345' at the end of the commit message. Should you have a bug reference?Please address any problems by updating the GitHub PR.
When complete, mark this comment as 'Done' and click the [blue 'Reply' button](https://go.dev/wiki/GerritBot#i-left-a-reply-to-a-comment-in-gerrit-but-no-one-but-me-can-see-it) above. These findings are based on heuristics; if a finding does not apply, briefly reply here saying so.
To update the commit title or commit message body shown here in Gerrit, you must edit the GitHub PR title and PR description (the first comment) in the GitHub web interface using the 'Edit' button or 'Edit' menu entry there. Note: pushing a new commit to the PR will not automatically update the commit message used by Gerrit.
For more details, see:
- [how to update commit messages](https://go.dev/wiki/GerritBot/#how-does-gerritbot-determine-the-final-commit-message) for PRs imported into Gerrit.
- the Go project's [conventions for commit messages](https://go.dev/doc/contribute#commit_messages) that you should follow.
(In general for Gerrit code reviews, the change author is expected to [log in to Gerrit](https://go-review.googlesource.com/login/) with a Gmail or other Google account and then close out each piece of feedback by marking it as 'Done' if implemented as suggested or otherwise reply to each review comment. See the [Review](https://go.dev/doc/contribute#review) section of the Contributing Guide for details.)
Should I squash the commits to a single commit and or keep this MR with fine-grained commits, one commit per package (more or less how it is right now)? I'll edit the commit messages in any case.
Acknowledged
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Rafael DinizI spotted some possible problems with your PR:
1. The commit title should start with the primary affected package name followed by a colon, like "net/http: improve [...]".
2. The first word in the commit title after the package should be a lowercase English word (usually a verb).
3. You usually need to reference a bug number for all but trivial or cosmetic fixes. For this repo, the format is usually 'Fixes #12345' or 'Updates #12345' at the end of the commit message. Should you have a bug reference?Please address any problems by updating the GitHub PR.
When complete, mark this comment as 'Done' and click the [blue 'Reply' button](https://go.dev/wiki/GerritBot#i-left-a-reply-to-a-comment-in-gerrit-but-no-one-but-me-can-see-it) above. These findings are based on heuristics; if a finding does not apply, briefly reply here saying so.
To update the commit title or commit message body shown here in Gerrit, you must edit the GitHub PR title and PR description (the first comment) in the GitHub web interface using the 'Edit' button or 'Edit' menu entry there. Note: pushing a new commit to the PR will not automatically update the commit message used by Gerrit.
For more details, see:
- [how to update commit messages](https://go.dev/wiki/GerritBot/#how-does-gerritbot-determine-the-final-commit-message) for PRs imported into Gerrit.
- the Go project's [conventions for commit messages](https://go.dev/doc/contribute#commit_messages) that you should follow.
(In general for Gerrit code reviews, the change author is expected to [log in to Gerrit](https://go-review.googlesource.com/login/) with a Gmail or other Google account and then close out each piece of feedback by marking it as 'Done' if implemented as suggested or otherwise reply to each review comment. See the [Review](https://go.dev/doc/contribute#review) section of the Contributing Guide for details.)
Rafael DinizShould I squash the commits to a single commit and or keep this MR with fine-grained commits, one commit per package (more or less how it is right now)? I'll edit the commit messages in any case.
Acknowledged
I happen to notice it looked like you pushed a new commit with a cleaned-up commit message to the GitHub PR. It looks like the commit message here in Gerrit is not yet updated.
In case it helps, here is a link to a reminder on how to update the Gerrit commit message for PRs imported into Gerrit:
https://go.dev/wiki/GerritBot/#how-does-gerritbot-determine-the-final-commit-message
Note that just pushing a new commit to the GitHub PR does not update the Gerrit commit message here.
Sorry, it's not quite a standard GitHub PR workflow.
After making changes in the GitHub web UI, be sure to then double-check the plain text shown in the Gerrit commit message (above) after the GitHub PR is imported into Gerrit to confirm you see your expected changes here.
Should I squash the commits to a single commit and or keep this MR with fine-grained commits [...]
You can upload as many commits to the GitHub PR as you like. GerritBot will handle squashing your commits into one change that Gerrit can handle.
There are some more details here:
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Thanks a lot for all the references. Already updated the Gerrit commit message.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
There's still a problem with `runtime/sys_plan9_arm64.s` with rather amusing consequences:
```
cpu% ls -l lib/cache/go-build/f?
--rw-rw-rw- M 66 miller miller 10 Sep 28 1906 lib/cache/go-build/f0/f0ee9d7b8fbb0afac809cb6c46cee7fd3a68befdf643ccdd00533820a8926177-d
--rw-rw-rw- M 66 miller miller 175 Jan 21 1969 lib/cache/go-build/f1/f14b3be5d7964adcd8b70771002d2c7131550f47ff5b3acc36394514ecef55b8-a
--rw-rw-rw- M 66 miller miller 21 Aug 19 1920 lib/cache/go-build/f5/f502da81ad708823cb5ea6c61b7f07f3b49cd9d264dff170551d11c9c7f2f4bb-d
--rw-rw-rw- M 66 miller miller 175 Sep 19 1935 lib/cache/go-build/f7/f78fa6e66dfe2f70dd6f903d19bd2cd8d67611422a009f1290830eefb4c9cec9-a
--rw-rw-rw- M 66 miller miller 8874542 Sep 5 1906 lib/cache/go-build/fb/fbbd15b647dbc50179a6bea2abd6aa099a209a7a57ba38c812cb43eea2dc2477-d
```
The return argument offsets in `runtime/timesplit` are wrong, as you will see if you run `go vet`:
```
term% go vet runtime
# runtime
# [runtime]
/home/miller/go-plan9-arm64/src/runtime/sys_plan9_arm64.s:186:1: [arm64] timesplit: invalid offset sec+0(FP); expected sec+8(FP)
/home/miller/go-plan9-arm64/src/runtime/sys_plan9_arm64.s:187:1: [arm64] timesplit: invalid offset nsec+8(FP); expected nsec+16(FP)
/home/miller/go-plan9-arm64/src/runtime/sys_plan9_arm64.s:198:1: [arm64] walltime: function walltime missing Go declaration
```
But fixing that will not be sufficient to make `time.Now` for plan9-arm64 correct, because the logic of the `timesplit` function is also not right. Anyway on 64-bit ARM, there's no need for the clever gyrations used on 32-bit ARM to simulate divide and remainder. I suggest this simpler version for arm64:
```
// func timesplit(u uint64) (sec int64, nsec int32)
TEXT runtime·timesplit(SB), NOSPLIT, $0-20
MOVD u+0(FP), R0
MOVD R0, R1
MOVD $1000000000, R2
UDIV R2, R1
MUL R1, R2
SUB R2, R0
MOVD R1,sec+8(FP)
MOVWU R0,nsec+16(FP)
RET
```
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
There seem to be other intermittent problems, as I found on another attempt to run `go vet`:
```
term% go vet -asmdecl runtime
go-plan9-arm64/src/crypto/internal/sysrand/rand.go:10:2: open /home/miller/go-plan9-arm64/src/os/types_windows.go: bad arg in system call
term% go vet -asmdecl runtime
# net [runtime.test]
fatal error: unexpected signal during runtime execution
[signal sys: trap: fault read code=0x0 addr=0x0 pc=0x84e5c]
runtime stack:
runtime.throw({0xa1c8f8?, 0x7f514?})
go-plan9-arm64/src/runtime/panic.go:1229 +0x38 fp=0x1fffeeab8 sp=0x1fffeea88 pc=0x95ef8
runtime.sigpanic()
go-plan9-arm64/src/runtime/os_plan9.go:78 +0x3a8 fp=0x1fffeeb08 sp=0x1fffeeab8 pc=0x5dba8
runtime.(*unwinder).resolveInternal(0x9d120?, 0x7c?, 0xe6?)
go-plan9-arm64/src/runtime/traceback.go:258 +0x1c fp=0x1fffeeb98 sp=0x1fffeeb18 pc=0x84e5c
runtime.(*unwinder).initAt(0x1fffeecc0?, 0x2cbbc?, 0x1fffeecc0?, 0x6fc5c?, 0x48058808?, 0xa0?)
go-plan9-arm64/src/runtime/traceback.go:225 +0x1cc fp=0x1fffeec88 sp=0x1fffeeb98 pc=0x84c1c
runtime.(*unwinder).init(...)
go-plan9-arm64/src/runtime/traceback.go:130
runtime.copystack(0x48488960, 0x2000)
go-plan9-arm64/src/runtime/stack.go:976 +0x46c fp=0x1fffeee48 sp=0x1fffeec88 pc=0x7a18c
runtime.newstack()
go-plan9-arm64/src/runtime/stack.go:1187 +0x62c fp=0x1fffeef68 sp=0x1fffeee48 pc=0x7afec
runtime.morestack()
go-plan9-arm64/src/runtime/asm_arm64.s:507 +0x70 fp=0x1fffeef68 sp=0x1fffeef68 pc=0x9b250
...
# go/build
# [go/build]
panic: assertion failed [recovered, repanicked]
goroutine 1 [running]:
go/types.(*Checker).handleBailout(0x4829f000, 0x486c9ad8)
go-plan9-arm64/src/go/types/check.go:404 +0x94
panic({0x68b760?, 0x341f00?})
go-plan9-arm64/src/runtime/panic.go:860 +0x12c
internal/pkgbits.assert(...)
go-plan9-arm64/src/internal/pkgbits/support.go:11
internal/pkgbits.(*Decoder).Bool(0x486c5680)
go-plan9-arm64/src/internal/pkgbits/decoder.go:365 +0xdc
go/internal/gcimporter.(*reader).typInfo(0x486c5680)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:254 +0x30
go/internal/gcimporter.(*pkgReader).objDictIdx(0x480d4c60, 0xb)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:574 +0x148
go/internal/gcimporter.(*pkgReader).objIdx(0x480d4c60, 0xb)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:477 +0x23c
go/internal/gcimporter.(*reader).obj(0x486c5bf8)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:440 +0x80
go/internal/gcimporter.(*reader).doTyp(0x486c5bf8)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:302 +0x80
go/internal/gcimporter.(*pkgReader).typIdx(0x480d4c60, {0x1f?, 0x0?}, 0x48246de0)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:279 +0x10c
go/internal/gcimporter.(*reader).typ(0x486c5ee8)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:249 +0x40
go/internal/gcimporter.(*reader).structType(0x486c5ee8)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:342 +0xbc
go/internal/gcimporter.(*reader).doTyp(0x486c5ee8)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:328 +0x33c
go/internal/gcimporter.(*pkgReader).typIdx(0x480d4c60, {0x5?, 0x0?}, 0x48246de0)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:279 +0x10c
go/internal/gcimporter.(*reader).typ(0x486c61d0)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:249 +0x40
go/internal/gcimporter.(*pkgReader).objIdx(0x480d4c60, 0x7)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:520 +0x3c8
go/internal/gcimporter.(*reader).obj(0x486c6488)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:440 +0x80
go/internal/gcimporter.(*reader).doTyp(0x486c6488)
go-plan9-arm64/src/go/internal/gcimporter/ureader.go:302 +0x80
... etc
```
I wonder how thoroughly you have tested this port? Getting it to compile cleanly is only the first step.
I'll investigate, my bad.
There's still a problem with `runtime/sys_plan9_arm64.s` with rather amusing consequences:
Rafael Diniz
Changed. Thanks Dr. Miller!
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I should be fixed in Patchset 11.
go vet runtime now runs.
Some improvements of the arm64 Plan9 port.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Are the tests all running successfully for you? I'm seeing quite a few failures running `go tool dist test` on 9legacy:
```
FAIL compress/flate 9.490s
FAIL crypto/internal/fips140test 22.370s
FAIL go/internal/gcimporter 54.334s
FAIL internal/abi 2.932s
FAIL internal/godebugs 24.807s
FAIL internal/trace 58.438s
FAIL net/http 905.455s
FAIL net/http/httputil 900.798s
FAIL net/http/internal/http2 36.653s
FAIL runtime 149.852s
FAIL strconv 0.476s
FAIL testing 10.889s
FAIL cmd/addr2line 9.112s
FAIL cmd/compile/internal/importer 66.427s
FAIL cmd/compile/internal/inline/inlheur 11.493s
FAIL cmd/compile/internal/ssa 8.931s
FAIL cmd/compile/internal/test 115.702s
FAIL cmd/compile/internal/types2 179.038s
FAIL cmd/cover 39.653s
FAIL cmd/internal/archive 5.731s
FAIL cmd/internal/moddeps 76.040s
FAIL cmd/internal/obj 5.400s
FAIL cmd/internal/testdir 17.440s
FAIL cmd/link 67.860s
FAIL cmd/link/internal/ld 33.456s
FAIL cmd/pack 13.090s
```
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| SLSA-Policy-Verified | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Thanks Dr. Miller. I just did a commit (Patchset 12) which fixes some issues (and add some workarounds for some tests so they pass at this point). I finally have a setup with qemu-aarch64 so I can test the changes faster.
Still lots of errors. I suggest you submit a patch when you have ALL tests passing on real hardware. (Qemu is unlikely to be duplicating multicore behaviour accurately enough to pick up concurrency bugs.)
| SLSA-Policy-Verified | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I managed to pass now many of the tests (go test dist), but there are some errors with networking, and some related to memory:
If it is ok, I might submit a couple more patchsets, as I want to address the remaining issues separately. Then I'll fire up the Pi 4 to run the tests after the non-multicore-related errors are fixed.
go tool dist test -run=^archive/tar$
ok archive/tar 4.658s
ok archive/zip 1.322s
ok bufio 0.666s
ok bytes 1.092s
ok cmp 0.217s
ok compress/bzip2 0.539s
ok compress/flate 3.946s
ok compress/gzip 8.524s
ok compress/lzw 0.401s
ok compress/zlib 0.508s
ok container/heap 0.359s
ok container/list 0.325s
ok container/ring 0.315s
ok context 1.789s
ok crypto 31.565s
ok crypto/aes 0.588s
ok crypto/cipher 16.763s
ok crypto/des 0.381s
ok crypto/dsa 0.279s
ok crypto/ecdh 0.601s
ok crypto/ecdsa 0.793s
ok crypto/ed25519 0.709s
ok crypto/elliptic 0.405s
ok crypto/fips140 0.492s
ok crypto/hkdf 0.345s
ok crypto/hmac 0.538s
ok crypto/hpke 8.548s
ok crypto/internal/boring 0.300s
? crypto/internal/boring/bbig [no test files]
ok crypto/internal/boring/bcache 0.886s
? crypto/internal/boring/sig [no test files]
? crypto/internal/constanttime [no test files]
? crypto/internal/cryptotest [no test files]
? crypto/internal/entropy [no test files]
? crypto/internal/entropy/v1.0.0 [no test files]
ok crypto/internal/fips140 0.284s
ok crypto/internal/fips140/aes 0.368s
ok crypto/internal/fips140/aes/gcm 0.249s [no tests to run]
? crypto/internal/fips140/alias [no test files]
ok crypto/internal/fips140/bigmod 0.542s
? crypto/internal/fips140/check [no test files]
? crypto/internal/fips140/check/checktest [no test files]
ok crypto/internal/fips140/drbg 0.235s [no tests to run]
ok crypto/internal/fips140/ecdh 0.302s
ok crypto/internal/fips140/ecdsa 0.440s
? crypto/internal/fips140/ed25519 [no test files]
ok crypto/internal/fips140/edwards25519 0.644s
ok crypto/internal/fips140/edwards25519/field 0.370s
? crypto/internal/fips140/hkdf [no test files]
? crypto/internal/fips140/hmac [no test files]
ok crypto/internal/fips140/mldsa 3.237s
ok crypto/internal/fips140/mlkem 0.804s
ok crypto/internal/fips140/nistec 0.291s [no tests to run]
ok crypto/internal/fips140/nistec/fiat 0.258s [no tests to run]
? crypto/internal/fips140/pbkdf2 [no test files]
ok crypto/internal/fips140/rsa 0.632s
? crypto/internal/fips140/sha256 [no test files]
? crypto/internal/fips140/sha3 [no test files]
? crypto/internal/fips140/sha512 [no test files]
? crypto/internal/fips140/ssh [no test files]
ok crypto/internal/fips140/subtle 0.301s
? crypto/internal/fips140/tls12 [no test files]
? crypto/internal/fips140/tls13 [no test files]
ok crypto/internal/fips140cache 0.440s
ok crypto/internal/fips140deps 3.870s
? crypto/internal/fips140deps/byteorder [no test files]
? crypto/internal/fips140deps/cpu [no test files]
? crypto/internal/fips140deps/godebug [no test files]
? crypto/internal/fips140deps/time [no test files]
? crypto/internal/fips140hash [no test files]
ok crypto/internal/fips140only 3.510s
ok crypto/internal/fips140test 24.638s
? crypto/internal/impl [no test files]
? crypto/internal/rand [no test files]
? crypto/internal/randutil [no test files]
ok crypto/internal/sysrand 0.540s
? crypto/internal/sysrand/internal/seccomp [no test files]
ok crypto/md5 0.550s
ok crypto/mlkem 0.427s
? crypto/mlkem/mlkemtest [no test files]
ok crypto/pbkdf2 0.330s
ok crypto/rand 1.090s
ok crypto/rc4 0.401s
ok crypto/rsa 1.855s
ok crypto/sha1 0.472s
ok crypto/sha256 0.492s
ok crypto/sha3 3.976s
ok crypto/sha512 0.502s
ok crypto/subtle 0.671s
--- FAIL: TestGetClientCertificate (0.18s)
--- FAIL: TestGetClientCertificate/TLSv12 (0.09s)
handshake_client_test.go:2472: #1: client error: EOF
--- FAIL: TestGetClientCertificate/TLSv13 (0.09s)
handshake_client_test.go:2474: #2: expected client error "GetClientCertificate", but got "EOF"
--- FAIL: TestTLSUniqueMatches (0.02s)
tls_test.go:504: write tcp 127.0.0.1:53628->127.0.0.1:36547: write /net/tcp/4/data: i/o on hungup channel
tls_test.go:519: EOF
FAIL
FAIL crypto/tls 11.553s
? crypto/tls/internal/fips140tls [no test files]
ok crypto/x509 26.803s
? crypto/x509/pkix [no test files]
ok database/sql 1.414s
ok database/sql/driver 0.273s
ok debug/buildinfo 1.033s
ok debug/dwarf 1.222s
ok debug/elf 1.307s
ok debug/gosym 0.603s
ok debug/macho 0.398s
ok debug/pe 1.612s
ok debug/plan9obj 0.302s
ok embed 0.375s [no tests to run]
ok embed/internal/embedtest 0.237s
? encoding [no test files]
ok encoding/ascii85 0.197s
ok encoding/asn1 0.448s
ok encoding/base32 0.421s
ok encoding/base64 0.365s
ok encoding/binary 0.388s
ok encoding/csv 0.439s
ok encoding/gob 20.558s
ok encoding/hex 0.300s
ok encoding/json 2.197s
ok encoding/pem 1.318s
ok encoding/xml 0.626s
ok errors 0.252s
ok expvar 0.517s
ok flag 0.599s
ok fmt 0.893s
ok go/ast 0.557s
ok go/build 77.374s
ok go/build/constraint 0.280s
ok go/constant 0.406s
ok go/doc 1.368s
ok go/doc/comment 23.407s
ok go/format 0.330s
ok go/importer 10.624s
ok go/internal/gccgoimporter 0.758s
ok go/internal/gcimporter 75.176s
ok go/internal/srcimporter 30.868s
ok go/parser 1.475s
ok go/printer 1.914s
ok go/scanner 0.388s
ok go/token 1.147s
ok go/types 204.694s
ok go/version 0.318s
ok hash 0.357s
ok hash/adler32 0.273s
ok hash/crc32 0.356s
ok hash/crc64 0.333s
ok hash/fnv 0.312s
ok hash/maphash 1.186s
ok html 0.415s
ok html/template 1.491s
ok image 0.795s
ok image/color 0.260s
? image/color/palette [no test files]
ok image/draw 0.855s
ok image/gif 0.996s
? image/internal/imageutil [no test files]
ok image/jpeg 8.162s
ok image/png 1.920s
ok index/suffixarray 1.091s
ok internal/abi 1.671s
? internal/asan [no test files]
? internal/bisect [no test files]
ok internal/buildcfg 0.245s
? internal/bytealg [no test files]
? internal/byteorder [no test files]
? internal/cfg [no test files]
ok internal/chacha8rand 0.396s
ok internal/copyright 17.321s
? internal/coverage [no test files]
? internal/coverage/calloc [no test files]
ok internal/coverage/cfile 25.225s
ok internal/coverage/cformat 0.326s
ok internal/coverage/cmerge 0.211s
? internal/coverage/decodecounter [no test files]
? internal/coverage/decodemeta [no test files]
? internal/coverage/encodecounter [no test files]
? internal/coverage/encodemeta [no test files]
ok internal/coverage/pods 0.438s
? internal/coverage/rtcov [no test files]
ok internal/coverage/slicereader 0.297s
ok internal/coverage/slicewriter 0.308s
? internal/coverage/stringtab [no test files]
ok internal/coverage/test 0.477s
? internal/coverage/uleb128 [no test files]
ok internal/cpu 0.466s
ok internal/dag 0.365s
ok internal/diff 0.376s
? internal/exportdata [no test files]
? internal/filepathlite [no test files]
ok internal/fmtsort 0.476s
ok internal/fuzz 0.454s
ok internal/gate 0.360s
? internal/goarch [no test files]
ok internal/godebug 9.549s
ok internal/godebugs 0.333s
? internal/goexperiment [no test files]
? internal/goos [no test files]
? internal/goroot [no test files]
ok internal/gover 0.320s
? internal/goversion [no test files]
? internal/lazyregexp [no test files]
? internal/lazytemplate [no test files]
? internal/msan [no test files]
? internal/nettrace [no test files]
? internal/obscuretestdata [no test files]
? internal/oserror [no test files]
ok internal/pkgbits 0.204s
ok internal/platform 14.850s
ok internal/poll 0.534s
ok internal/profile 0.371s
? internal/profilerecord [no test files]
? internal/race [no test files]
ok internal/reflectlite 0.550s
ok internal/runtime/atomic 0.446s
ok internal/runtime/cgroup 0.583s
? internal/runtime/exithook [no test files]
? internal/runtime/gc [no test files]
? internal/runtime/gc/internal/gen [no test files]
ok internal/runtime/gc/scan 0.213s
ok internal/runtime/maps 2.606s
ok internal/runtime/math 0.260s
? internal/runtime/pprof/label [no test files]
ok internal/runtime/sys 0.300s
ok internal/runtime/wasitest 0.405s
ok internal/saferio 0.497s
ok internal/singleflight 0.531s
ok internal/strconv 1.217s
? internal/stringslite [no test files]
ok internal/sync 3.120s
ok internal/synctest 9.001s
? internal/syscall/execenv [no test files]
ok internal/syscall/unix 0.251s
ok internal/sysinfo 0.409s
? internal/syslist [no test files]
ok internal/testenv 5.627s
? internal/testhash [no test files]
? internal/testlog [no test files]
? internal/testpty [no test files]
ok internal/trace 288.211s
? internal/trace/internal/testgen [no test files]
ok internal/trace/internal/tracev1 1.065s
? internal/trace/raw [no test files]
ok internal/trace/testtrace 0.621s
ok internal/trace/tracev2 0.676s
? internal/trace/traceviewer [no test files]
? internal/trace/traceviewer/format [no test files]
? internal/trace/version [no test files]
? internal/txtar [no test files]
ok internal/types/errors 25.771s
ok internal/unsafeheader 0.557s
ok internal/xcoff 1.337s
ok internal/zstd 1.314s
ok io 1.251s
ok io/fs 2.026s
ok io/ioutil 18.554s
ok iter 0.712s
ok log 0.474s
? log/internal [no test files]
ok log/slog 1.218s
? log/slog/internal [no test files]
ok log/slog/internal/benchmarks 0.693s
ok log/slog/internal/buffer 0.468s
? log/syslog [no test files]
ok maps 0.610s
ok math 0.705s
ok math/big 45.741s
ok math/big/internal/asmgen 0.964s
ok math/bits 1.333s
ok math/cmplx 0.531s
ok math/rand 1.926s
ok math/rand/v2 2.166s
ok mime 0.631s
ok mime/multipart 10.931s
ok mime/quotedprintable 0.973s
ok net 9.976s
--- FAIL: TestAutomaticHTTP2_ListenAndServe_GetCertificate (0.04s)
(...)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Most of the changes in this patch set appear to be related to running a builder on 9front instead of Plan 9. The patches are disabling tests which have run successfully for years on Plan 9 and 9legacy builders. 9front is a fork of Plan 9 which seems to have diverged so far as to be unable to run normal go tests. The title of this CL is "add plan9/arm64 port". I suggest sticking the to goal of passing all tests on Plan 9 with arm64. Porting to 9front can be a separate project.
if os.IsNotExist(bestErr) {Returning an error was the correct thing to do. If the cert file doesn't exist, it's not right to pretend it does. If you apply 9legacy patch ca.diff on the builder, the file will be there as needed.
if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) &&This defeats the purpose of the test. Plan 9 correctly returns a NoSuchHost error. If 9front is returning something else, it's the 9front implementation which needs to be fixed.
if !err.(*DNSError).IsNotFound &&As above.
if runtime.GOOS == "plan9" {This test is supported on Plan 9. Considerable work has been done (eg CL 420715) to ensure that it passes. If it breaks on a 9front builder, fix the 9front problem, don't disable the test.
if runtime.GOOS == "plan9" {This test passes on Plan 9; it's a 9front problem.
if testing.Short() && goos.IsPlan9 != 0 && goarch.IsArm64 != 0 {This test passes on plan9-arm. If it times out on plan9-arm64 this seems to be a regression. Better to find and fix the plan9-arm64 problem than fudge the test.
if goos.IsPlan9 != 0 && goarch.IsArm64 != 0 {The solution to exhausting physical memory is to enable swap space on the builder.
func skipPageAllocSimulationOnPlan9Arm64(t *testing.T) {The solution to physical memory exhaustion is to enable swap space on the builder.
func skipPageCacheSimulationOnPlan9Arm64(t *testing.T) {The solution to exhausting physical memory is to enable swap space on the builder.
Most tests passing now. Hopefully no more arm64 port issues.
Done
Much improved stability, tests passing now.
Most of the changes in this patch set appear to be related to running a builder on 9front instead of Plan 9. The patches are disabling tests which have run successfully for years on Plan 9 and 9legacy builders. 9front is a fork of Plan 9 which seems to have diverged so far as to be unable to run normal go tests. The title of this CL is "add plan9/arm64 port". I suggest sticking the to goal of passing all tests on Plan 9 with arm64. Porting to 9front can be a separate project.
Thanks Dr. Miller.
Done, I reverted the "waivers", and now all tests are passing. 0 test failures:
https://github.com/rafael2knokia/go/blob/plan9-arm64-dev/misc/plan9/arm64/test-report.md
if os.IsNotExist(bestErr) {Returning an error was the correct thing to do. If the cert file doesn't exist, it's not right to pretend it does. If you apply 9legacy patch ca.diff on the builder, the file will be there as needed.
Indeed. Thanks for the pointer.
if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) &&This defeats the purpose of the test. Plan 9 correctly returns a NoSuchHost error. If 9front is returning something else, it's the 9front implementation which needs to be fixed.
Correct, reverted.
if !err.(*DNSError).IsNotFound &&Rafael DinizAs above.
Reverted.
if runtime.GOOS == "plan9" {This test is supported on Plan 9. Considerable work has been done (eg CL 420715) to ensure that it passes. If it breaks on a 9front builder, fix the 9front problem, don't disable the test.
Fixed. I needed some small patching in 9front to get it passed (branch with the fixes here): https://github.com/rafael2knokia/9front/tree/tcpsplice-close-fix
if runtime.GOOS == "plan9" {This test passes on Plan 9; it's a 9front problem.
Reverted.
if testing.Short() && goos.IsPlan9 != 0 && goarch.IsArm64 != 0 {This test passes on plan9-arm. If it times out on plan9-arm64 this seems to be a regression. Better to find and fix the plan9-arm64 problem than fudge the test.
Fixed.
if goos.IsPlan9 != 0 && goarch.IsArm64 != 0 {The solution to exhausting physical memory is to enable swap space on the builder.
Reverted. Tests are passing now with swap.
func skipPageAllocSimulationOnPlan9Arm64(t *testing.T) {The solution to physical memory exhaustion is to enable swap space on the builder.
Reverted. Test are passing now.
func skipPageCacheSimulationOnPlan9Arm64(t *testing.T) {The solution to exhausting physical memory is to enable swap space on the builder.
| Code-Review | +1 |
Port is stable (as much as it can be on Plan 9).
if os.IsNotExist(bestErr) {Rafael DinizReturning an error was the correct thing to do. If the cert file doesn't exist, it's not right to pretend it does. If you apply 9legacy patch ca.diff on the builder, the file will be there as needed.
Indeed. Thanks for the pointer.
Done
if runtime.GOOS == "plan9" {Rafael DinizThis test is supported on Plan 9. Considerable work has been done (eg CL 420715) to ensure that it passes. If it breaks on a 9front builder, fix the 9front problem, don't disable the test.
Fixed. I needed some small patching in 9front to get it passed (branch with the fixes here): https://github.com/rafael2knokia/9front/tree/tcpsplice-close-fix
Done
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I have built this by bootstrapping from plan9-arm. Then, when I try to populate the cache with arm64 packages using the plan9-arm64 compiler, I get errors like this:
```
# internal/byteorder
<unknown line number>: internal compiler error: panic: intrinsic already exists for internal/runtime/atomic.Loaduintptr on s390x
goroutine 1 [running]:
runtime/debug.Stack()
goroot/src/runtime/debug/stack.go:26 +0x64
cmd/compile/internal/base.FatalfAt({0x147c7d0?, 0x0?}, {0xaed72e, 0x9}, {0x4c04c048, 0x1, 0x1})
goroot/src/cmd/compile/internal/base/print.go:232 +0x210
cmd/compile/internal/base.Fatalf(...)
goroot/src/cmd/compile/internal/base/print.go:197
cmd/compile/internal/gc.handlePanic()
goroot/src/cmd/compile/internal/gc/main.go:58 +0x90
panic({0x147c7d0?, 0x4c392e80?})
goroot/src/runtime/panic.go:859 +0x120
cmd/compile/internal/ssagen.intrinsicBuilders.add(0x4c3968a0, 0x15d58e8, {0xb182cd, 0x17}, {0xaf367b, 0xb}, 0x14f3168)
goroot/src/cmd/compile/internal/ssagen/intrinsics.go:51 +0x160
cmd/compile/internal/ssagen.intrinsicBuilders.alias(0x4c3968a0?, {0xb182cd, 0x17}, {0xaf367b, 0xb}, {0xb182cd, 0x17}, {0xae3ef8, 0x6}, {0x4c3b8280, ...})
goroot/src/cmd/compile/internal/ssagen/intrinsics.go:80 +0xf8
cmd/compile/internal/ssagen.initIntrinsics.func3(...)
goroot/src/cmd/compile/internal/ssagen/intrinsics.go:132
cmd/compile/internal/ssagen.initIntrinsics(0x0?)
goroot/src/cmd/compile/internal/ssagen/intrinsics.go:695 +0x2438
cmd/compile/internal/ssagen.InitTables(...)
goroot/src/cmd/compile/internal/ssagen/ssa.go:217
cmd/compile/internal/gc.Main(0x14f2d00)
goroot/src/cmd/compile/internal/gc/main.go:215 +0xbfc
main.main()
goroot/src/cmd/compile/main.go:57 +0x100
```
and this
```
# crypto/subtle
panic: d.nx != 0
goroutine 17 [running]:
crypto/internal/fips140/sha256.(*Digest).checkSum(...)
goroot/src/crypto/internal/fips140/sha256/sha256.go:230
crypto/internal/fips140/sha256.(*Digest).Sum(0x4c416300, {0x4c434160, 0x0, 0x20})
goroot/src/crypto/internal/fips140/sha256/sha256.go:204 +0x258
crypto/sha256.Sum256(...)
goroot/src/crypto/sha256/sha256.go:60
cmd/internal/hash.Sum32({0x4c42a178, 0x8, 0x8})
goroot/src/cmd/internal/hash/hash.go:27 +0x98
cmd/internal/obj.(*Link).GCLocalsSym(...)
goroot/src/cmd/internal/obj/sym.go:243
cmd/compile/internal/liveness.(*Liveness).emit(0x4c4222c0)
goroot/src/cmd/compile/internal/liveness/plive.go:1387 +0x478
cmd/compile/internal/liveness.Compute(0x4c4f8640, 0x4c444000, 0x0, 0x4c428540, 0x0)
goroot/src/cmd/compile/internal/liveness/plive.go:1433 +0x894
cmd/compile/internal/ssagen.genssa(0x4c444000, 0x4c428540)
goroot/src/cmd/compile/internal/ssagen/ssa.go:6988 +0xbc
cmd/compile/internal/ssagen.Compile(0x4c4f8640, 0x0, 0x4c3d4000?)
goroot/src/cmd/compile/internal/ssagen/pgen.go:314 +0x480
cmd/compile/internal/gc.compileFunctions.func2()
goroot/src/cmd/compile/internal/gc/compile.go:177 +0x6c
created by cmd/compile/internal/gc.compileFunctions in goroutine 1
goroot/src/cmd/compile/internal/gc/compile.go:163 +0x108
```
and this
```
# time
panic: runtime error: slice bounds out of range [1280375023:64]
goroutine 33 [running]:
crypto/internal/fips140/sha256.(*Digest).Write(0x4c6bf140, {0x4c6bf0b8?, 0x32, 0x82909c?})
goroot/src/crypto/internal/fips140/sha256/sha256.go:176 +0x254
crypto/internal/fips140/sha256.(*Digest).checkSum(...)
goroot/src/crypto/internal/fips140/sha256/sha256.go:227
crypto/internal/fips140/sha256.(*Digest).Sum(0x4e5dff00, {0x4e840920, 0x0, 0x20})
goroot/src/crypto/internal/fips140/sha256/sha256.go:204 +0xec
crypto/sha256.Sum256(...)
goroot/src/crypto/sha256/sha256.go:60
cmd/internal/hash.Sum32({0x4e5e18d0, 0xe, 0x10})
goroot/src/cmd/internal/hash/hash.go:27 +0x98
cmd/internal/obj.(*Link).GCLocalsSym(...)
goroot/src/cmd/internal/obj/sym.go:243
cmd/compile/internal/liveness.(*Liveness).emit(0x4c143760)
goroot/src/cmd/compile/internal/liveness/plive.go:1387 +0x478
cmd/compile/internal/liveness.Compute(0x4d15dcc0, 0x4c6881c0, 0x30, 0x4e848240, 0x0)
goroot/src/cmd/compile/internal/liveness/plive.go:1433 +0x894
cmd/compile/internal/ssagen.genssa(0x4c6881c0, 0x4e848240)
goroot/src/cmd/compile/internal/ssagen/ssa.go:6988 +0xbc
cmd/compile/internal/ssagen.Compile(0x4d15dcc0, 0x0, 0x4c5060b8?)
goroot/src/cmd/compile/internal/ssagen/pgen.go:314 +0x480
cmd/compile/internal/gc.compileFunctions.func2()
goroot/src/cmd/compile/internal/gc/compile.go:177 +0x6c
created by cmd/compile/internal/gc.compileFunctions in goroutine 1
goroot/src/cmd/compile/internal/gc/compile.go:163 +0x108
```
and this
```
# cmd/vendor/github.com/google/pprof/internal/graph
<unknown line number>: internal compiler error: panic: runtime error: invalid memory address or nil pointer dereference
goroutine 1 [running]:
runtime/debug.Stack()
/usr/miller/goroot/src/runtime/debug/stack.go:26 +0x64
cmd/compile/internal/base.FatalfAt({0x4c04e128?, 0x0?}, {0xaed72e, 0x9}, {0x4c04e158, 0x1, 0x1})
/usr/miller/goroot/src/cmd/compile/internal/base/print.go:232 +0x210
cmd/compile/internal/base.Fatalf(...)
/usr/miller/goroot/src/cmd/compile/internal/base/print.go:197
cmd/compile/internal/gc.handlePanic()
/usr/miller/goroot/src/cmd/compile/internal/gc/main.go:58 +0x90
panic({0x1489b20?, 0x15912d0?})
/usr/miller/goroot/src/runtime/panic.go:859 +0x120
cmd/compile/internal/ssagen.initIntrinsics(0x50?)
/usr/miller/goroot/src/cmd/compile/internal/ssagen/intrinsics.go:114 +0x214
cmd/compile/internal/ssagen.InitTables(...)
/usr/miller/goroot/src/cmd/compile/internal/ssagen/ssa.go:217
cmd/compile/internal/gc.Main(0x14f2d00)
/usr/miller/goroot/src/cmd/compile/internal/gc/main.go:215 +0xbfc
main.main()
/usr/miller/goroot/src/cmd/compile/main.go:57 +0x100
```
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I rebooted the plan9 system using `*ncpu=1` to run on a single core. This time the arm64 native rebuild (`go build std cmd`) succeeded with no errors.
Have you tested this release on true SMP hardware, or only on an emulation of multiple cores? There may be a subtle flaw somewhere which is only triggered by some detail of the hardware behaviour (MMU TLB, caches, memory reordering) that isn't being accurately emulated on your test platform.
I've now run `go tool dist test` (on just one core) and it does seem more reliable now. Well done.
In that test, there was one panic in `ssagen.initIntrinsics`, which suggests that SMP is exacerbating the problem but not causing it.
The other notable failure was the `runtime` test running forever, with address space expanded to the full available 4GB. Is this what you would expect for memory usage? What's the maximum user address space on the 9front platform you are using for tests?
I've now run `go tool dist test` (on just one core) and it does seem more reliable now. Well done.
In that test, there was one panic in `ssagen.initIntrinsics`, which suggests that SMP is exacerbating the problem but not causing it.
The other notable failure was the `runtime` test running forever, with address space expanded to the full available 4GB. Is this what you would expect for memory usage? What's the maximum user address space on the 9front platform you are using for tests?
The infinite loop in `runtime.test` was my fault -- a kernel bug which I've now fixed. Thanks for flushing it out!
I have built this by bootstrapping from plan9-arm. Then, when I try to populate the cache with arm64 packages using the plan9-arm64 compiler, I get errors like this:
Looks like this was a problem in my kernel too, also now corrected.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Thanks again for the detailed review. Summary of where PS15 stands, point by point:
1. Compiler-heap corruption (initIntrinsics / sha256 garbage / 'intrinsic already exists on s390x'): I think I found the mechanism. plan9/arm64 was the only Plan 9 port returning heap pages to the OS during sysUnused, via segfree (mem_plan9_arm64.go). Dropping a page's physical backing that way is unsafe under SMP unless the kernel guarantees a cross-core TLB shootdown: another core can keep a stale mapping and read/write the page after it's recycled, corrupting unrelated live allocations. In PS15 sysUnusedOS is now a no-op on plan9/arm64, matching plan9/{386,arm,amd64}; the segment reservation is kept. I want to be upfront about my testing: I can only run under QEMU/TCG, and it does NOT reproduce this - the exact packages from your crash logs, go build -a -p 4, ran 5 clean fresh-cache iterations on 4 emulated cores even WITHOUT the fix. So TCG isn't exercising the TLB path, consistent with your point that emulation won't reproduce multicore behaviour. I therefore cannot claim from my side that the panics are gone - could you retest PS15 on real hardware?
2. Disabling tests that pass on Plan 9 / 9legacy (PS13): you were right, and I've reverted all of them. PS15 no longer touches crypto/x509/root_plan9.go, net/{lookup,timeout,writev}_test.go, or runtime/{goroutineleakprofile,mgcscavenge,mpagealloc,mpagecache}_test.go. Where I'd seen failures they traced to the 9front loopback tcpsplice kernel bug (fixed 9front-side) and the segfree corruption above, not to anything needing a waiver.
3. ABI/timesplit/walltime (PS3, PS9): fixed. open/dupfd now 8-byte-align the int32 syscall args as you described; timesplit uses the simpler arm64 UDIV/MUL/SUB form you suggested (sec+8/nsec+16); walltime is a Go function again. go vet -asmdecl runtime and syscall are both clean.
4. Real SMP hardware (PS14): honestly, so far only QEMU/TCG, which as you noted won't model MMU/TLB/cache/reordering - the segfree bug is a concrete instance of exactly that. I don't yet have physical multicore arm64 results; I'll arrange hardware testing and won't ask for another substantive review until I can report real-hardware results.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |