1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# Go on 9front
All verified on `lab.qcow2`, not inferred.
## Go 1.24.x is broken on plan9/amd64
Every binary dies before `main`:
M structure uses sizeclass 1792/0x700 bytes; incompatible with mutex flag mask 0x3ff
fatal error: runtime.m memory alignment too small for spinbit mutex
runtime.lockVerifyMSize() lock_spinbit.go:97
The spinbit mutex landed in 1.24 and `runtime.m` falls in a sizeclass that
cannot meet its alignment. Tested: **1.23.11 ok, 1.24.4 broken, 1.25.14 ok,
1.27.0 ok**. The host's installed Go is 1.24.4 -- precisely the broken one --
so `mk.sh` pins `GOTOOLCHAIN=go1.27.0`.
## TLS needs a CA bundle you supply
Go's x509 looks only at `/sys/lib/tls/ca.pem` on plan9, and 9front ships
none:
SystemCertPool ERR: open /sys/lib/tls/ca.pem: file does not exist
Copy any bundle there and HTTPS works -- verified TLS 1.3 with full cert
verification. Already installed on `lab.qcow2`.
## Networking is /net, not a helper program
Go opens `/net/tcp/clone`, writes `connect`, and resolves through
`/net/cs` and `/net/dns` (`net/fd_plan9.go`, `net/ipsock_plan9.go`). No
`exec.Command`, no webfs. It is what `dial(2)` does.
## No native graphics yet
`9fans.net/go/draw` is a complete libdraw port and *builds* for
`GOOS=plan9`, but at runtime it does
cmd := exec.Command(devdraw, os.Args[0], "(devdraw)")
which is plan9port's helper. 9front has no `devdraw`. A native transport
means opening `/dev/draw` and reading `/dev/mouse`, `/dev/kbd` -- plain
file I/O, no cgo, a few hundred lines under an already-complete library.
Nobody has written it.
## Building
Cross-compile from Linux; do not put a toolchain on the guest. A native
plan9/amd64 toolchain builds fine via `bootstrap.bash` (needs a bootstrap
Go >= 1.24.6), but it is 249MB unpacked -- `compile` alone is 27MB --
against a 3MB `ical/fs`.
Getting binaries in, with an HTTP server on the host:
hget http://10.0.2.2:8099/fs > /tmp/icalfs # qemu user-net host
## The guest clock is skewed by the host's timezone
`run.sh` passes `-rtc base=localtime`, so the guest's idea of *UTC* equals
the host's *local* time. With the host on EDT the guest is 4h behind real
UTC. Anything time-sensitive must be generated in the guest's frame --
take `date -n` from the guest, not from the host.
|