summaryrefslogtreecommitdiff
path: root/open_issues
diff options
context:
space:
mode:
Diffstat (limited to 'open_issues')
-rw-r--r--open_issues/serverbootv2.mdwn899
1 files changed, 899 insertions, 0 deletions
diff --git a/open_issues/serverbootv2.mdwn b/open_issues/serverbootv2.mdwn
new file mode 100644
index 00000000..9702183e
--- /dev/null
+++ b/open_issues/serverbootv2.mdwn
@@ -0,0 +1,899 @@
+[[!meta copyright="Copyright © 2024 Free Software
+Foundation, Inc."]]
+
+[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable
+id="license" text="Permission is granted to copy, distribute and/or modify this
+document under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no Invariant
+Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license
+is included in the section entitled [[GNU Free Documentation
+License|/fdl]]."]]"""]]
+
+
+# ServerBootV2 RFC Draft
+
+[[!inline pagenames=hurd/what_is_an_os_bootstrap raw=yes feeds=no]]
+
+The Hurd's current bootstrap, [[Quiet-Boot|hurd/bootstrap]] (a biased
+and made-up name), is fragile, hard to debug, and complicated:
+
+* `Quiet-boot` chokes on misspelled or missing boot arguments. When
+ this happens, the Hurd bootstrap will likely hang and display
+ nothing. This is tricky to debug.
+* `Quiet-Boot` is hard to change. For instance, when the Hurd
+ developers added `acpi`, the `pci-arbiter`, and `rumpdisk`, they
+ struggled to get `Quiet-Boot` working again.
+* `Quiet-Boot` forces each bootstrap task to include special bootstrap
+ logic to work. This limits what is possible during the
+ bootstrap. For instance, it should be trivial for the Hurd to
+ support netboot, but `Quiet-Boot` makes it hard to add `nfs`,
+ `pfinet`, and `isofs` to the bootstrap.
+* `Quiet-Boot` hurts other Hurd distributions too. When Guix
+ developers updated their packaged version of the Hurd, that included
+ support for SATA drives, a simple misspelled boot argument halted
+ their progress for a few weeks.
+
+The alternative `ServerBoot V2` proposal (which was discussed on
+[irc](https://logs.guix.gnu.org/hurd/2023-07-18.log) and is similar to
+the previously discussed [bootshell
+proposal](https://mail-archive.com/bug-hurd@gnu.org/msg26341.html))
+aims to code all or most of the bootstrap specific logic into one
+single task (`/hurd/serverboot`). `Serverboot V2` has a number
+of enticing advantages:
+
+* It simplifies the hierarchical dependency of translators during
+ bootstrap. Developers should be able to re-order and add new
+ bootstrap translators with minimal work.
+* It gives early bootstrap translators like `auth` and `ext2fs`
+ standard input and output which lets them display boot errors. It
+ also lets signals work.
+* One can trivially use most Hurd translators during the
+ bootstrap. You just have to link them statically.
+* `libmachdev` could be simplified to only expose hardware to
+ userspace; it might even be possible to remove it entirely. Also
+ the `pci-arbiter`, `acpi`, and `rumpdisk` could be simplified.
+* Developers could remove any bootstrap logic from `libdiskfs`, which
+ detects the bootstrap filesystem, starts the `exec` server, and
+ spawns `/hurd/startup`. Instead,`libdiskfs` would only focus on
+ providing filesystem support.
+* If an error happens during early boot, the user could be dropped
+ into a REPL or mini-console, where he can try to debug the issue.
+ We might call this `Bootshell V2`, in reference to the original
+ proposal. This could be written in lisp. Imagine having an
+ extremely powerful programming language available during bootstrap
+ that is only [436 bytes!](https://justine.lol/sectorlisp2)
+* It would simplify the code for subhurds by removing the logic from
+ each task that deals with the OS bootstrap.
+
+Now that you know why we should use `Serverboot V2`, let's get more
+detailed. What is `Serverboot V2` ?
+
+`Serverboot V2` would be an empty filesystem dynamically populated
+during bootstrap. It would use a `netfs` like filesystem that will
+populate as various bootstrap tasks are started. For example,
+`/servers/socket2` will be created once `pfinet` starts. It also
+temporarily pretends to be the Hurd process server, `exec`, and `/`
+filesystem while providing signals and `stdio`. Let's explain how
+`Serverboot V2` will bootstrap the Hurd.
+
+**FIXME The rest of this needs work.**
+
+Any bootstrap that the Hurd uses will probably be a little odd,
+because there is an awkward and circular startup-dance between
+`exec`, `ext2fs`, `startup`, `proc`, `auth`, the `pci-arbiter`,
+`rumpdisk`, and `acpi` in which each translator oddly depends on the
+other during the bootstrap, as this ascii art shows.
+
+
+ pci-arbiter
+ |
+ acpi
+ |
+ rumpdisk
+ |
+ ex2fs -- storeio
+ / \
+ exec startup
+ / \
+ auth proc
+
+
+This means that there is no *perfect* Hurd bootstrap design. Some
+designs are better in some ways and worse in others. `Serverboot V2`
+would simplify other early bootstrap tasks, but all that complicated
+logic would be in one binary. One valid criticism of `Serverboot V2`
+is that it will may be a hassle to develop and maintain. In any case,
+trying to code the *best* Hurd bootstrap may be a waste of time. In
+fact, the Hurd bootstrap has been rewritten several times already.
+Our fearless leader, Samuel, feels that rewriting the Hurd bootstrap
+every few years may be a waste of time. Now that you understand why
+Samuel's discourages a Hurd bootstrap rewrite, let's consider why we
+should develop `Serverboot V2`.
+
+# How ServerBoot V2 will work
+
+Bootstrap begins when Grub and GNU Mach start some tasks, and then GNU
+Mach resumes the not-yet-written
+`/hurd/serverboot`. `/hurd/serverboot` is the only task to accept
+special ports from the kernel via command line arguments like
+`--kernel-task`; `/hurd/serverboot` tries to implement/emulate as much
+of the normal Hurd environment for the other bootstrap translators.
+In particular, it provides the other translators with `stdio`, which
+lets them read/write without having to open the Mach console device.
+This means that the various translators will be able to complain about
+their bad arguments or other startup errors, which they cannot
+currently do.
+
+`/hurd/serverboot` will provide a basic filesystem with netfs, which
+gives the other translators a working `/` directory and `cwd`
+ports. For example, `/hurd/serverboot`, would store its port at
+`/dev/netdde`. When `/hurd/netdde` starts, it will reply to its
+parent with `fsys_startup ()` as normal.
+
+`/hurd/serverboot` will also emulate the native Hurd process server to
+early bootstrap tasks. This will allow early bootstrap tasks to get
+the privileged (device master and kernel task) ports via the normal
+glibc function `get_privileged_ports (&host_priv, &device_master).`
+Other tasks will register their message ports with the emulated
+process server. This will allow signals and messaging during the
+bootstrap. We can even use the existing mechanisms in glibc to set and
+get init ports. For example, when we start the `auth` server, we will
+give every task started thus far, their new authentication port via
+glibc's `msg_set_init_port ()`. When we start the real proc server,
+we query it for proc ports for each of the tasks, and set them the
+same way. This lets us migrate from the emulated proc server to the
+real one.
+
+**Fix me: Where does storeio (storeio with**
+`device:@/dev/rumpdisk:wd0`**), rumpdisk, and the pci-arbiter come
+in?**
+
+Next, we start `ext2fs`. We reattach all the running translators from
+our `netfs` bootstrap filesystem onto the new root. We then send
+those translators their new root and cwd ports. This should happen
+transparently to the translators themselves!
+
+# Supporting Netboot
+
+`Serverboot V2` could trivially support netboot by adding `netdde`,
+`pfinet` (or `lwip`), and `isofs` as bootstrap tasks. The bootstrap
+task will start the `pci-arbiter`, and `acpi` (FIXME add some more
+detail to this sentence). The bootstrap task starts `netdde`, which
+will look up any `eth` devices (using the device master port, which it
+queries via the fake process server interface), and sends its fsys
+control port to the bootstrap task in the regular `fsys_startup
+()`. The bootstrap task sets the fsys control port as the translator
+on the `/dev/netdde` node in its `netfs` bootstrap fs. Then
+`/hurd/serverboot` resumes `pfinet`, which looks up
+`/dev/netdde`. Then `pfinet` returns its `fsys` control port to the
+bootstrap task, which it sets on `/servers/socket/2`. Then bootstrap
+resumes `nfs`, and `nfs` just creates a socket using the regular glibc
+socket () call, and that looks up `/servers/socket/2`, and it just
+works. **FIXME where does isofs fit in here?**
+
+Then `nfs` gives its `fsys` control port to `/hurd/serverboot`, which
+knows it's the real root filesystem, so it take the netdde's and
+pfinet's fsys control ports. Then it calls `file_set_translator ()`
+on the nfs on the same paths, so now `/dev/netdde` and
+`/servers/socket/2` exist and are accessible both on our bootstrap fs,
+and on the new root fs. The bootstrap can then take the root fs to
+broadcast a root and cwd port to all other tasks via a
+`msg_set_init_port ()`. Now every task is running on the real root fs,
+and our little bootstrap fs is no longer used.
+
+`/hurd/serverboot` can resume the exec server (which is the first
+dynamically-linked task) with the real root fs. Then we just
+`file_set_translator ()` on the exec server to `/servers/exec`, so
+that `nfs` doesn't have to care about this. The bootstrap can now
+spawn tasks, instead of resuming ones loaded by Mach and grub, so it
+next spawns the `auth` and `proc` servers and gives everyone their
+`auth` and `proc` ports. By that point, we have enough of a Unix
+environment to call `fork()` and `exec()`. Then the bootstrap tasks
+would do the things that `/hurd/startup` used to do, and finally
+spawns (or execs) `init / PID 1`.
+
+With this scheme you will be able to use ext2fs to start to your root
+fs via as `/hurd/ext2fs.static /dev/wd0s1`. This eliminates boot
+arguments like `--magit-port` and `--next-task`.
+
+This also simplifies `libmachdev`, which exposes devices to userspace
+via some Mach `device_*` RPC calls, which lets the Hurd contain device
+drivers instead of GNU Mach. Everything that connects to hardware can
+be a `machdev`.
+
+Additionally, during the `Quiet Boot` bootstrap,`libmachdev` awkwardly
+uses `libtrivfs` to create a transient `/` directory, so that the
+`pci-arbiter` can mount a netfs on top of it at bootstrap.
+`libmachdev` needs `/servers/bus` to mount `/pci,`and it also
+needs `/servers` and `/servers/bus` (and `/dev`, and
+`/servers/socket`). That complexity could be moved to `ServerbootV2`,
+which will create directory nodes at those locations.
+
+`libmachdev` provides a trivfs that intercepts the `device_open` rpc,
+which the `/dev` node uses. It also fakes a root filesystem node, so
+you can mount a `netfs` onto it. You still have to implement
+`device_read` and `device_write` yourself, but that code runs in
+userspace. An example of this can be found in
+`rumpdisk/block-rump.c`.
+
+`libpciaccess` is a special case: it has two modes, the first time it
+runs via `pci-arbiter`, it acquires the pci config IO ports and runs
+as x86 mode. Every subsequent access of pci becomes a hurdish user of
+pci-arbiter.
+
+`rumpdisk` exposes `/dev/rumpdisk`:
+
+```
+$ showtrans /dev/rumpdisk
+ /hurd/rumpdisk
+```
+
+
+# FAQ
+
+## `Server Boot V2` looks like a ramdisk + a script...?
+
+Its not quite a ramdisk, its more a netfs translator that
+creates a temporary `/`. Its a statically linked binary. I don't
+think it differs from a multiboot module.
+
+## How are the device nodes on the bootstrap netfs attached to each translator?
+## How does the first non-bootstrap task get invoked?
+## does bootstrap resume it?
+## Could we just use a ram disk instead?
+## One could stick an unionfs on top of it to load the rest of the system after bootstrap.
+
+It looks similar to a ramdisk in principle, i.e. it exposes a fs which
+lives only in ram, but a ramdisk would not help with early bootstrap.
+Namely during early bootstrap, there are no signals or console.
+Passing control from from one server to the next via a bootstrap port
+is a kludge at best. How many times have you seen the bootstrap
+process hang and just sit there? `Serverboot V2` would solve that.
+Also, it would allow subhurds to be full hurds without special casing
+each task with bootstrap code. It would also clean up `libmachdev`,
+and Damien, its author, is in full support.
+
+## A ramdisk could implement signals and stdio. Isn't that more flexible?
+
+But if its a ramdisk essentially you have to provide it with a tar
+image. Having it live inside a bootstrap task only is
+preferable. Also the task could even exit when its done whether you
+use an actual ramdisk or not. You still need to write the task that
+boots the system. That is different than how it works currently. Also
+a ramdisk would have to live in mach, and we want to move things out
+of mach.
+
+Additionally, the bootstrap task will be loaded as the first multiboot
+module by grub. It's not a ramdisk, because a ramdisk has to contain
+some fs image (with data), and we'd need to parse that format. It
+might make sense to steer it more into that direction (and Samuel
+seems to have preferred it), because there could potentially be some
+config files, or other files that the servers may need to run. I'm not
+super fond of that idea. I'd prefer the bootstrap fs to be just a
+place where ports (translators) can be placed and looked up. Actually
+in my current code it doesn't even use `netfs`, it just implements the
+RPCs directly. I'll possibly switch to `netfs` later, or if the
+implementation stays simple, I won't use `netfs`.
+
+## Serverboot V2 just rewrites proc and exec. Why reimplement so much code?
+
+I don't want to exactly reimplement full `proc` and `exec` servers in the
+bootstrap task, it's more of providing very minimal emulation of some
+of their functions. I want to implement the two RPCs from the
+`proc` interface, one to give a task the privileged ports on request and
+one to let the task give me its msg port. That seems fairly simple to
+me.
+
+While we were talking of using netfs, my actual implementation doesn't
+even use that, it just implements the RPCs directly (not to suggest I
+have anything resembling a complete implementation). Here's some
+sample code to give you an idea of what it is like
+
+
+ error_t
+ S_proc_getprivports (struct bootstrap_task *task,
+ mach_port_t *host_priv,
+ mach_port_t *device_master)
+ {
+ if (!task)
+ return EOPNOTSUPP;
+
+ if (bootstrap_verbose)
+ fprintf (stderr, "S_proc_getprivports from %s\n", task->name);
+
+ *host_priv = _hurd_host_priv;
+ *device_master = _hurd_device_master;
+
+ return 0;
+ }
+
+ error_t
+ S_proc_setmsgport (struct bootstrap_task *task,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ mach_port_t newmsgport,
+ mach_port_t *oldmsgport,
+ mach_msg_type_name_t *oldmsgportPoly)
+ {
+ if (!task)
+ return EOPNOTSUPP;
+
+ if (bootstrap_verbose)
+ fprintf (stderr, "S_proc_setmsgport for %s\n", task->name);
+
+ *oldmsgport = task->msgport;
+ *oldmsgportPoly = MACH_MSG_TYPE_MOVE_SEND;
+
+ task->msgport = newmsgport;
+
+ return 0;
+ }
+
+Yes, it really is just letting tasks fetch the priv ports (so
+`get_privileged_ports ()` in glibc works) and set their message ports.
+So much for a slippery slope of reimplementing the whole process
+server :)
+
+
+## Let's bootstrap like this: initrd, proc, exec, acpi, pci, drivers,
+## unionfs+fs with every server executable included in the initrd tarball?
+
+I don't see how that's better, but you would be able to try something
+like that with my plan too. The OS bootstrap needs to start servers
+and integrate them into the eventual full hurd system later when the
+rest of the system is up. When early servers start, they're running
+on bare Mach with no processes, no `auth`, no files or file
+descriptors, etc. I plan to make files available immediately (if not
+the real fs), and make things progressively more "real" as servers
+start up. When we start the root fs, we send everyone their new root
+`dir` port. When we start `proc`, we send everyone their new `proc`
+port. and so on. At the end, all those tasks we have started in
+early boot are full real hurd proceses that are not any different to
+the ones you start later, except that they're statically linked, and
+not actually `io map`'ed from the root fs, but loaded by Mach/grub
+into wired memory.
+
+# IRC Logs
+
+ <damo22> showtrans /dev/wd0 and you can open() that node and it will
+ act as a device master port, so you can then `device_open` () devices
+ (like wd0) inside of it, right?
+
+ oh it's a storeio, that's… cute. that's another translator we'd need
+ in early boot if we want to boot off /hurd/ext2fs.static /dev/wd0
+
+ <damo22> We implemented it as a storeio with
+ device:@/dev/rumpdisk:wd0
+
+ so the `@` sign makes it use the named file as the device master, right?
+
+ <damo22> the `@` symbol means it looks up the file as the device
+ master yes. Instead of mach, but the code falls back to looking up
+ mach, if it cant be found.
+
+ I see it's even implemented in libstore, not in storeio, so it just
+ does `file_name_lookup ()`, then `device_open` on that.
+
+ <damo22> pci-arbiter also needs acpi because the only way to know the
+ IRQ of a pci device reliably is to use ACPI parser, so it totally
+ implements the Mach `device_*` functions. But instead of handling the
+ RPCs directly, it sets the callbacks into the
+ `machdev_device_emulations_ops` structure and then libmachdev calls
+ those. Instead of implementing the RPCs themselves, It abstracts them,
+ in case you wanted to merge drivers. This would help if you wanted
+ multiple different devices in the same translator, which is of course
+ the case inside Mach, the single kernel server does all the devices.
+
+ but that shouldn't be the case for the Hurd translators, right? we'd
+ just have multiple different translators like your thing with rumpdisk
+ and rumpusb.
+
+ `<damo22>` i dont know
+
+ ok, so other than those machdev emulation dispatch, libmachdev uses
+ trivfs and does early bootstrap. pci-arbiter uses it to centralize the
+ early bootstrap so all the machdevs can use the same code. They chain
+ together. pci-arbiter creates a netfs on top of the trivfs. How
+ well does this work if it's not actually used in early bootstrap?
+
+ <damo22> and rumpdisk opens device ("pci"), when each task is resumed,
+ it inherits a bootstrap port
+
+ and what does it do with that? what kind of device "pci" is?
+
+ <damo22> its the device master for pci, so rumpdisk can call
+ pci-arbiter rpcs on it
+
+ hm, so I see from the code that it returns the port to the root of its
+ translator tree actually. Does pci-arbiter have its own rpcs? does it
+ not just expose an fs tree?
+
+ <damo22> it has rpcs that can be called on each fs node called
+ "config" per device: hurd/pci.defs. libpciaccess uses these.
+
+ how does that compare to reading and writing the fs node with regular read and write?
+
+ <damo22> so the second and subsequent instances of pciaccess end up
+ calling into the fs tree of pci-arbiter. you can't call read/write on
+ pci memory its MMIO, and the io ports need `inb`, `inw`, etc. They
+ need to be accessed using special accessors, not a bitstream.
+
+ but I can do $ hexdump /servers/bus/pci/0000/00/02/0/config
+
+ <damo22> yes you can on the config file
+
+ how is that different from `pci_conf_read` ? it calls that.
+
+ <damo22> the `pci fs` is implemented to allow these things.
+
+ why is there a need for `pci_conf_read ()` as an RPC then, if you can
+ instead use `io_read` on the "config" node?
+
+ <damo22> i am not 100% sure. I think it wasn't fully implemented from
+ the beginning, but you definitely cannot use `io_read ()` on IO
+ ports. These have explicit x86 instructions to access them
+ MMIO. maybe, im not sure, but it has absolute physical addressing.
+
+ I don't see how you would do this via `pci.defs` either?
+
+ <damo22> We expose all the device tree of pci as a netfs
+ filesystem. It is a bus of devices. you may be right. It would be best
+ to implement pciaccess to just read/write from the filesystem once its
+ exposed on the netfs.
+
+ yes, the question is:
+
+ 1 is there anything that you can do by using the special RPCs from
+ pci.defs that you cannot do by using the regular read/write/ls/map
+ on the exported filsystem tree,
+ 2 if no, why is there even a need for `pci.defs`, why not always use
+ the fs? But anyway, that's irrelevant for the question of bootstrap
+ and libmachdev
+
+ <damo22> There is a need for rpcs for IO ports.
+
+ Could you point me to where rumpdisk does `device_open ("pci")`? grep
+ doesn't show anything. which rpcs are for the IO ports?
+
+ <damo22> They're not implemented yet we are using raw access I
+ think. The way it works, libmachdev uses the next port, so it all
+ chains together: `libmachdev/trivfs_server.c`.
+
+ but where does it call `device_open ("pci")` ?
+
+ <damo22> when the pci task resumes, it has a bootstrap port, which is
+ passed from previous task. There is no `device_open ("pci")`. or if
+ its the first task to be resumed, it grabs a bootstrap port from
+ glibc? im not sure
+
+ ok, so if my plan is implemented how much of `libmachdev` functionality
+ will still be used / useful?
+
+ <damo22> i dont know. The mach interface? device interface\*. maybe
+ it will be useless.
+
+ I'd rather you implemented the Mach device RPCs directly, without the
+ emulation structure, but that's an unrelated change, we can leave that
+ in for now.
+
+ <damo22> I kind of like the emulation structure as a list of function
+ pointers, so i can see what needs to be implemented, but that's
+ neither here nor there. `libmachdev` was a hack to make the bootstrap
+ work to be honest.…and we'd no longer need that. I would be happy if
+ it goes away. the new one would be so much better.
+
+ is there anything else I should know about this all? What else could
+ break if there was no libmachdev and all that?
+
+ <damo22> acpi, pci-arbiter, rumpdisk, rumpusbdisk
+
+ right, let's go through these
+
+ <damo22> The pci-arbiter needs to start first to claim the x86 config
+ io ports. Then gnumach locks these ports. No one else can use them.
+
+ so it starts and initializes **something** what does it need? the
+ device master port, clearly, right? that it will get through the
+ glibc function / the proc API
+
+ <damo22> it needs a /servers/bus and the device master
+
+ <solid_black>
+ right, so then it just does fsys_startup, and the bootstrap task
+ places it onto `/servers/bus` (it's not expected to do
+ `file_set_translator ()` itself, just as when running as a normal
+ translator)
+
+ <damo22> it exposes a netfs on `/servers/bus/pci`
+
+ <solid_black> so will pci-arbiter still expose mach devices? a mach
+ device master? or will it only expose an fs tree + pci.defs?
+
+ <damo22> i think just fs tree and pci.defs. should be enough
+
+ <solid_black> ok, so we drop mach dev stuff from pci-arbiter
+ completely. then acpi starts up, right? what does it need?
+
+ <damo22> It needs access to `pci.defs` and the pci tree. It
+ accesses that via libpciaccess, which calls a new mode that
+ accesses the fstree. It looks up `servers/bus/pci`.
+
+ ok, but how does that work now then?
+
+ <damo22> It looks up the right nodes and calls pci.defs on them.
+
+ <solid_black> looks up the right node on what? there's no root
+ filesystem at that point (in the current scheme)
+
+ `<damo22>` It needs pci access
+
+ that's why I was wondering how it does `device_open ("pci")`
+
+ <damo22> I think libmachdev from pci gives acpi the fsroot. there is a
+ doc on this.
+
+ so does it set the root node of pci-arbiter as the root dir of acpi?
+ as in, is acpi effectively chrooted to `/servers/bus/pci`?
+
+ <damo22> i think acpi is chrooted to the parent of /servers. It shares
+ the same root as pci's trivfs.
+
+ i still don't quite understand how netfs and trivfs within pci-arbiter interact.
+
+ <damo22> you said there would be a fake /. Can't acpi use that?
+
+ <solid_black> yeah, in my plan / the new bootstrap scheme, there'll be
+ a / from the very start.
+
+ <damo22> ok so acpi can look up /servers/bus/pci, and it will exist.
+
+ and pci-arbiter can really sit on `/servers/bus/pci` (no need for
+ trivfs there at all) and acpi will just look up
+ `/servers/bus/pci`. And we do not need to change anything in acpi to
+ get it to do that.
+
+ And how does it do it now? maybe we'd need to remove some
+ no-longer-required logic from acpi then?
+
+ <damo22> it looks up device ("pci") if it exists, otherwise it falls
+ back to `/servers/bus/pci`.
+
+ Ah hold on, maybe I do understand now. currently pci-arbiter exposes
+ its mach dev master as acpi-s mach dev master. So it looks up
+ device("pci") and finds it that way.
+
+ <damo22> correct, but it doesnt need that if the `/` exists.
+
+ yeah, we could remove this in the new bootstrap scheme, and just
+ always open the fs node (or leave it in for compatibility, we'll see
+ about that). acpi just sits on `/servers/acpi/tables`.
+
+ `rumpdisk` runs next and it needs `/servers/bus/pci`, `pci.defs`, and
+ `/servers/acpi/tables`, and `acpi.defs`. It exposes `/dev/rumpdisk`.
+
+ Would it make sense to make rumpdisk expose a tree/directory of Hurd
+ files and not Mach devices? This is not necessary for anything, but
+ just might be a nice little cleanup.
+
+ <damo22> well, it could expose a tree of block devices, like
+ `/dev/rumpdisk/ide/1`.
+
+ <solid_black> and then `ln -s /rumpdisk/ide/1 /dev/wd1`. and no need
+ for an intermediary storeio. plus the Hurd file interface is much
+ richer than Mach device, you can do fsync for instance.
+
+ <damo22> the rump kernel is bsd under the hood, so needs to be
+ `/dev/rumpdisk/ide/wd0`
+
+ <solid_black> You can just convert "ide/0" to "/dev/wd0" when
+ forwarding to the rump part. Not that I object to ide/wd0, but we can
+ have something more hierarchical in the exposed tree than old-school
+ unix device naming? Let's not have /dev/sda1. Instead let's have
+ /dev/sata/0/1, but then we'd still keep the bsd names as symlinks into
+ the *dev/rumpdisk*… tree
+
+ <damo22> sda sda1
+
+ <solid_black> good point
+
+ <damo22> 0 0/1
+
+ <solid_black> well, you can on the Hurd :D and we won't be doing that
+ either, rumpdisk only exposes the devices, not partitions
+
+ <damo22> well you just implement a block device on the directory? but
+ that would be confusing for users.
+
+ <solid_black> I'd expect rumpdisk to only expose device nodes, like
+ /dev/rumpdisk/ide/0, and then we'd have /dev/wd0 being a symlink to
+ that. And /dev/wd0s1 being a storeio of type part:1:/dev/wd0 or
+ instead of using that, you could pass that as an option to your fs,
+ like ext2fs -T typed part:1/dev/wd0
+
+ <damo22> where is the current hurd bootstrap (QuietBoot) docs hosted?
+ here:
+ https://git.savannah.gnu.org/cgit/hurd/web.git/plain/hurd/bootstrap.mdwn
+
+ <solid_black> so yeah, you could do the device tree thing I'm
+ proposing in rumpdisk, or you could leave it exposing Mach devices and
+ have a bunch of storeios pointing to that. So anyway, let's say
+ rumpdisk keeps exposing a single node that acts as a Mach device
+ master and it sits on /dev/rumpdisk.
+
+ <solid_black> Then we either need a storeio, or we could make ext2fs
+ use that directly. So we start `/hurd/ext2fs.static -T typed
+ part:1:@/dev/rumpdisk:wd0`.
+
+ <solid_black> I'll drop all the logic in libdiskfs for detecting if
+ it's the bootstrap filesystem, and starting the exec server, and
+ spawning /hurd/startup. It'll just be a library to help create
+ filesystems.
+
+ <solid_black> After that the bootstrap task migrates all those
+ translator nodes from the temporary / onto the ext2fs, broadcasts the
+ root and cwd ports to everyone, and off we go to starting auth and
+ proc and unix. sounds like it all would work indeed. so we're just
+ removing libmachdev completely, right?
+
+ <damo22> netdde links to it too. I think it has libmachdevdde
+
+ <solid_black> Also how would you script this thing. Like ideally we'd
+ want the bootstrap task to follow some sort of script which would say,
+ for example,
+
+ mkdir /servers
+ mkdir /servers/bus
+ settrans /servers/bus/pci ${pci-task} --args-to-pci
+ mkdir /dev
+ settrans /dev/netdde ${netdde-task} --args-to-netdde
+ setroot ${ext2fs-task} --args-to-ext2fs
+
+ <solid_black> and ideally the bootstrap task would implement a REPL
+ where you'd be able to run these commands interactively (if the
+ existing script fails for instance). It can be like grub, where it has
+ a predefined script, and you can do something (press a key combo?) to
+ instead run your own commands in a repl. or if it fails, it bails out
+ and drops you into the repl, yes. this gives you **so much more**
+ visibility into the boot process, because currently it's all scattered
+ across grub, libdiskfs (resuming exec, spawning /hurd/startup),
+ /hurd/startup, and various tricky pieces of logic in all of these
+ servers.
+
+ <solid_black> We could call the mini-repl hurdhelper? If something
+ fails, you're on your own, at best it prints an error message (if the
+ failing task manages to open the mach console at that point) Perhaps
+ we call the new bootstrap proposal Bootstrap.
+
+ <solid_black> When/if this is ready, we'll have to remove libmachdev
+ and port everything else to work without it.
+
+ <damo22> yes its a great idea. I'm not a fan of lisp either. If i
+ keep in mind that `/` is available early, then I can just clean up the
+ other stuff. and assume i have `/`, and the device master can be
+ accessed with the regular glibc function, and you can printf freely
+ (no need to open the console). Do i need to run `fsys_startup` ?
+
+ yes, exactly like all translators always do. Well you probably run
+ netfs_startup or whatever, and it calls that. you're not supposed to
+ call fsys_getpriv or fsys_init
+
+ <damo22> i think my early attempts at writing translators did not use
+ these, because i assumed i had `/`. Then i realised i didn\`t. And
+ libmachdev was born.
+
+ <solid-black> Yes, you should assume you have /, and just do all the
+ regular things you would do. and if something that you would usually
+ do doesn't work, we should think of a way to make it work by adding
+ more stuff in the bootstrap task when it's reasonable to, of
+ course. and please consider exposing the file tree from rumpdisk,
+ though that's orthogonal.
+
+ <damo22> you mean a tree of block devices?
+
+ <solid_black> Yes, but each device node would be just a Hurd (device)
+ file, not a Mach device. i.e. it'd support io_read and io_write, not
+ device_read and device_write. well I guess you could make it support
+ both.
+
+ <damo22> isnt that storeio's job?
+
+ <solid_black> if a node only implements the device RPCs, we need a
+ storeio to turn it into a Hurd file, yes. but if you would implement
+ the file RPCs directly, there wouldn't be a need for the intermediary
+ storeio, not that it's important.
+
+ <damo22> but thats writing storeio again. thing is, i dont know at
+ runtime which devices are exposed by rump. It auto probes them and
+ prints them out but i cant tell programmatically which ones were
+ detected, becuause rump knows which devices exist but doesn't expose
+ it over API in any way. Because it runs as a kernel would with just
+ one driver set.
+
+ <damo22> Rump is a decent set of drivers. It does not have better
+ hardware support than Linux drivers (of modern Linux)? Instead Rump is
+ netbsd in a can, and it's essentially unmaintained upstream
+ too. However, it still is used it to test kernel modules, but it lacks
+ makefiles to separate all drivers into modules. BUT using rump is
+ better than updating / redoing the linux drivers port of DDE, because
+ netbsd internal kernel API is much much more stable than linux. We
+ would fall behind in a week with linux. No one would maintain the
+ linux driver -> hurd port. Also, there is a framework that lets you
+ compile the netbsd drivers as userspace unikernels: rump. Such a
+ thing only does not exist for modern Linux. Rump is already good
+ enough for some things. It could replace netdde. It already works for
+ ide/sata.
+
+ <damo22> Rump it has its own /dev nodes on a rumpfs, so you can do
+ something like `rump_ls` it.
+
+ <damo22> Rump is a minimal netbsd kernel. It is just the device
+ drivers, and a bit of pthreading, and has only the drivers that you
+ link. So rumpdisk only has the ahci and ide drivers and nothing
+ else. Additionally rump can detect them off the pci bus.
+
+ <damo22> I will create a branch on
+ <http://git.zammit.org/hurd-sv.git> with cleaned translators.
+
+ <damo22> solid_black: i almost cleaned up acpi and pci-arbiter but
+ realised they are missing the shutdown notification when i strip out
+ libmachdev.
+
+ <solid-black>: "how are the device nodes on the bootstrap netfs attached to
+ each translator?" – I don't think I understand the question, please
+ clarify.
+
+ <damo22> I was wondering if the new bootstrap process can resume a fs
+ task and have all the previous translators wake up and serve their
+ rpcs. without needing to resume them. we have a problem with the
+ current design, if you implement what we discussed yesterday, the IO
+ ports wont work because they are not exposed by pci-arbiter yet. I am
+ working on it, but its not ready.
+
+ <solid_black> I still don't understand the problem. the bootstrap
+ task resumes others in order. the root fs task too, eventually, but
+ not before everything that hash to come up before the root fs task is
+ ready.
+
+ <damo22> I don't think it needs to be a disk. Literally a trivfs is enough.
+
+ <solid_black> why are I/O ports not exposed by pci-arbiter? why isn't
+ that in issue with how it works currently then?
+
+ <damo22> solid_black: we are using ioperm() in userspace, but i want
+ to refactor the io port usage to be granularly accessed. so one day
+ gnumach can store a bitmap of all io ports and reject more than one
+ range that overlaps ports that are in use. since only one user of any
+ port at any time is allowed. i dont know if that will allow users to
+ share the same io ports, but at least it will prevent users from
+ clobbering each others hw access.
+
+ <solid_black> damo22: (again, sorry for not understanding the hardware
+ details), so what would be the issue? when the pci arbiter starts,
+ doesn't it do all the things it has to do with the I/O ports?
+
+ <damo22> io ports are only accessed in raw method now. Any user can do
+ ioperm(0, 0xffff, 1) and get access to all of them
+
+ <solid_black> doesn't that require host priv or something like that?
+
+ <damo22> yeh probably. maybe only root can. But i want to allow
+ unprivileged users to access io ports by requesting exclusive access
+ to a range.
+
+ <solid_black> I see that ioperm () in glibc uses the device master
+ port, so yeah, root-only (good)
+
+ `<damo22>` first in locks the port range
+
+ <solid_black> but you're saying that there's someting about these I/O
+ ports that works today, but would break if we implemented what we
+ discussed yeasterday? what is it, and why?
+
+ `<damo22>` well it might still work. but there's a lot of changes to
+ be done in general
+
+ <solid_black> let me try to ask it in a different way then
+
+ <damo22> i just know a few of the specifics because i worked on them.
+
+ <solid_black> As I understand it, you're saying that 1: currently any
+ root process can request access to any range of I/O ports, and you
+ also want to allow **unprivileged** processes to get access to ranges
+ of I/O ports, via a new API of the PCI arbiter (but this is not
+ implemented yet, right?)
+
+ <damo22> yes
+
+ <solid_black> 2: you're saying that something about this would break /
+ be different in the new scheme, compared to the current scheme. i
+ don't understand the 2, and the relation between 1 and 2.
+
+ <damo22> 2 not really, I may have been mistaken it probably will
+ continue working fine. until i try to implement 1. ioperm calls
+ `i386_io_perm_create` and `i386_io__perm_modify` in the same system
+ call. I want to seperate these into the arbiter so the request goes
+ into pci-arbiter and if it succeeds, then the port is returned to the
+ caller and the caller can change the port access.
+
+ <solid_black> yes, so what about 2 will break 1 when you try to implement it?
+
+ <damo22> with your new bootstrap, we need `i386_io_perm_*` to be
+ accessible. im not sure how. is that a mach rpc?
+
+ <solid_black> these are mach rpcs. i386_io_perm_create is an rpc that
+ you do on device master.
+
+ <damo22> should be ok then
+
+ <solid_black> i386_io_perm_modify you do on you task port. yes, I
+ don't see how this would be problematic.
+
+ <damo22>: you might find this branch useful
+ <http://git.zammit.org/hurd-sv.git/log/?h=feat-simplify-bootstrap>
+
+ <solid_black> although:
+
+ 1. I'm not sure whether the task itself should be wiring its memory,
+ or if the bootstrap task should do it.
+ 2. why do you request startup notifications if you then never do
+ anything in `S_startup_dosync`?
+
+ <solid_black> same for essential tasks actaully, that should probably
+ be done by the bootstrap task and not the translator itself (but we'll
+ see)
+
+ <solid_black> 1. don't `mach_print`, just `fprintf (stderr, "")`
+ <solid_black> 2. please always verify the return result of
+ `mach_port_deallocate` (and similar functions),
+ typically like this:
+
+ err = mach_port_deallocate (…);
+ assert_perror_backtrace (err);
+
+ this helps catch nasty bugs.
+
+ <solid_black> 3. I wonder why both acpi and pci have their own
+ `pcifs_startup` and `acpifs_startup`; can't they use `netfs_startup
+ ()`?
+
+ `<damo22>` 1. no idea, 2. rumpdisk needed it, but these might
+ not 3. ACK, 4.ACK, 5. I think they couldnt use the `netfs_startup ()`
+ before but might be able to now. Anyway, this should get you booting
+ with your bootstrap translator (without rumpdisk). Rumpdisk seems to
+ use the `device_* RPC` from `libmachdev` to expose its device.
+ whereas pci and acpi dont use them for anything except `device_open`
+ to pass their port to the next translator. I think my latest patch
+ for io ports will work. but i need to rebuild glibc and libpciaccess
+ and gnumach. Why does libhurduser need to be in glibc? It's quite
+ annoying to add an rpc.
+
+ I think i have done gnumach io port locking, and pciaccess, but hurd
+ part needs work and then to merge it needs a rebuild of glibc because
+ of hurduser
+
+ <damo22> Why cant libhurduser be part of the hurd package?
+
+ I don't think I understnad enough of this to do a review, but I'd
+ still like to see the patch if it's available anywhere.
+
+ <damo22> ok i can push to my repos
+
+ <solid_black> glibc needs to use the Hurd RPCs (and implement some,
+ too), and glibc cannot depend on the Hurd package because the Hurd
+ package depends on glibc.
+
+ <damo22> lol ok
+
+ <solid_black> As things currently stand, glibc depends on the Hurd
+ **headers** (including mig defs), but not any Hurd binaries. still,
+ the cross build process is quite convoluted. I posted about it
+ somewhere: https://floss.social/@bugaevc/109383703992754691
+
+ <jpoiret> the manual patching of the build system that's needed to
+ bootstrap everything is a bit suboptimal.
+
+ <damo22> what if you guys submit patches upstream to glibc to add a
+ build target to copy the headers or whatever is needed? solid_black:
+ see
+ [http://git.zammit.org/{libpciaccess.git,gnumach.git](http://git.zammit.org/%7Blibpciaccess.git,gnumach.git)}
+ on fix-ioperm branches