[HN Gopher] Proposal: Add bare metal support to Go
___________________________________________________________________
Proposal: Add bare metal support to Go
Author : rbanffy
Score : 49 points
Date : 2025-05-07 19:44 UTC (3 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| Someone wrote:
| FTA: // printk emits a single 8-bit character to
| standard output // //go:linkname printk
| runtime.printk func printk(c byte)
|
| So, printing "Hello, world!", necessarily will have to make 13
| calls to this function. I think I would have required a _printk_
| that prints an array of bytes. I expect that can be significantly
| faster on lots of hardware.
|
| In contrast, there's // getRandomData generates
| len(b) random bytes and writes them into b //
| //go:linkname getRandomData runtime.getRandomData func
| getRandomData(b []byte)
|
| Here, they seem to acknowledge that it can be faster to make a
| single call.
| jeroenhd wrote:
| The method for printing uses an Intel UART driver to print
| characters. AFAIK, the standard low level UART generally only
| does single character transfers unless you write a (relatively)
| complex driver.
|
| Rendering per string is better per string, but I'm not so sure
| how bad the difference is when it comes to UART but I doubt the
| system has enough throughput for the first implementation to
| matter.
| 90s_dev wrote:
| I wonder if this is related to that bare metal bios os post
| from a week or so ago. I asked the author why he used tty asm
| calls to print instead of calling int 10 directly and he said
| it was more efficient, but for different reasons.
|
| https://news.ycombinator.com/item?id=43873822
| ronsor wrote:
| Arguably `printk(c byte)` should be `printck(c byte)`, and
| there should be a separate `printk(s []byte)` that handles an
| array of bytes.
|
| If `printk` isn't implemented, then fall back to repeated calls
| of `printck`.
| timewizard wrote:
| > Here, they seem to acknowledge that it can be faster to make
| a single call.
|
| It calls the internal Fill function to fill 4 bytes of the
| slice at a time. That calls the rng assembly stub function
| which uses 'rdrand' to get 32bits of random data. Which gets
| called len(b)/4 times.
|
| I don't think they did it for speed but rather to be more
| idiomatic.
|
| Anyways, OSDev has had a "Go Bare Bones" page for quite a
| while:
|
| https://wiki.osdev.org/Go_Bare_Bones
| jasonthorsness wrote:
| We use 'scratch' containers for many of our Go applications, so
| they have no user-space stuff other than our application binary.
| It reduces exposure for security vulnerabilities. This proposal
| seems to be taking that approach to the extreme - not even a
| kernel. Super-interesting; I wonder if it could run on cloud VMs?
| How tiny could the image become?
| jasonthorsness wrote:
| Looks like Tamago targets multiple VM runtimes
| https://github.com/usbarmory/tamago?tab=readme-ov-file
| veggieroll wrote:
| How do you handle temp file space, timezone data, and other
| things that a minimal image provide?
| kfreds wrote:
| Temp file space: Use RAM, or talk to host storage over
| Virtio.
|
| Timezone data etc: You would have to fetch that over the
| network, or from a metadata API such as the one Firecracker
| provides to VM guests.
| fpoling wrote:
| Services rarely need timezone done. So if one is OK with
| supporting only UTC, Go runtime works fine without any
| timezene data.
|
| We use a minimal image to run in on AWS Nitro VM and it
| contains only kernel, init.d, the Go application file and TLS
| certificate roots with the root filesystem mounted over
| tmpfs.
|
| Note that Nitro VM uses a custom kernel provided by AWS so
| the new proposal is not relevant for us. But if we could run
| Go directly in that VM, it will surely makes things faster
| and saves like 10% memory overhead. And it will also avoid
| OOM killer and few other bad unwanted interactions between Go
| runtime and Linux kernel memory management.
| kfreds wrote:
| > This proposal seems to be taking that approach to the extreme
| - not even a kernel.
|
| To be fair, there is a kernel - the Go runtime. But since there
| is no privilege separation it classifies as a unikernel.
| Performance gains should be expected compared to a system where
| you have to copy data to/from guest VM kernel space to guest VM
| user space.
|
| > I wonder if it could run on cloud VMs?
|
| Yes. TamaGo currently runs in KVM guests with the following
| VMMs: Cloud Hypervisor, Firecracker microvm, QEMU microvm.
|
| > How tiny could the image become?
|
| Roughly the same size as your current Go binary. TamaGo doesn't
| add much.
| ignoramous wrote:
| > _To be fair, there is a kernel - the Go runtime._
|
| I like Anil Madhavapeddy's definition for such setups. A
| compiler that just refuses to stop: MirageOS
| is a system written in pure OCaml where not only do common
| network protocols and file systems and high-level things like
| web servers and web stacks can all be expressed in OCaml but
| the compiler just refuses to stop ... compiler, instead of
| stopping and generating a binary that you then run inside
| Linux or Windows, will continue to specialize the application
| that it is compiling and ... emit a full operating system
| that can just boot by itself.
|
| https://signalsandthreads.com/what-is-an-operating-system /
| https://archive.vn/yLfkq
___________________________________________________________________
(page generated 2025-05-07 23:01 UTC)