From 43c1802f880471c5b69f8c622314827790aad0b8 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Fri, 26 Sep 2025 23:04:36 +0200 Subject: Initial commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miquel Sabaté Solà --- README.md | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 README.md (limited to 'README.md') diff --git a/README.md b/README.md new file mode 100644 index 0000000..f1b50d6 --- /dev/null +++ b/README.md @@ -0,0 +1,121 @@ +## Summary + +**pudc**: **P**ID **u** **d**iu **c**oses (which loosely translates to "PID 1 +utters stuff"). + +Yet another blog site, but this time around cooked like this: + +- The backend is written in a mixture of C and RISC-V assembly. +- The backend is actually PID1 (for real, not within a container). +- We poll and parse incoming HTTP requests ourselves. +- The frontend is a mere HTML page with [htmx](https://htmx.org/). + +In the end, this repository is more of an exercise in order to dig deeper into +the Linux kernel, its interfaces, the RISC-V architecture, and all the dragons +in between. + +## Build + +*NOTE*: if you are running on a non-RISCV machine, then you will need to do +cross compilation. This is easily achieved by installing the proper package from +your Linux distribution (e.g. for openSUSE it's `cross-riscv64-`) and +then setting the `CROSS_COMPILE` environment variable. This environment variable +is used pretty much like in the Linux Kernel and many other projects: it just +sets a prefix for `as`, `ld`, etc. + +You can build everything with the default `make` target. After that, you can use +QEMU in order to test the given binary. For that you need QEMU with RISC-V +support (i.e. the `qemu-system-riscv64` command), and you need to pass the +`LINUX_SOURCE` option with the path to the Linux kernel source code. Another +requirement is the file system. This is supposed to be available and, if we are +going to use QEMU, then you need to pass an image with a file system in it. You +can generate this image like so: + +```sh +$ qemu-img create -f raw disk.img 10G +$ sudo mkfs.{btrfs,ext4,whatever} -F disk.img +$ make qemu_prepare_disk +``` + +Note that the `qemu_prepare_disk` target will mount into `/mnt/pudc` this disk +and populate it with a minimal hierarchy and the executable produced by the +earlier `make` default target. If you want your image to be named in another +way, change the commands above and set the `MOUNT_DEST_IMAGE` environment +variable, as that will be used for the `qemu_prepare_disk` target. + +Compiling the Linux Kernel is pretty easy. If you are cross compiling you must +make sure that the `ARCH` environment variable is set to `riscv` and that the +`CROSS_COMPILE` one is also set as the toolchain prefix (just like the +instructions for this project). With that, the default configuration from `make +defconfig` will already give you support for virtualized RISC-V environments and +all SoCs. Otherwise, just select with `menuconfig` whatever it is that you need. + +With all of that, just run `make qemu`, which will start QEMU in `-nographic` +mode with the given Linux Kernel and the init program that was built from this +project. You can quit from QEMU in `-nographic` mode by pressing `Ctrl+A` and +then `X`. + +Hence, a complete run down on how to build and run this project (by using QEMU): + +``` sh +# Exporting variables. +$ export ARCH=riscv +$ export LINUX_SOURCE= +$ export CROSS_COMPILE=riscv64-suse-linux- # on openSUSE. Change it for your case. + +# Kernel +$ cd $LINUX_SOURCE +$ make defconfig +$ make -j $(nproc) +# -> your image is now at arch/riscv/boot/Image. + +# pudc +$ cd +## If you don't have an .img disk, then: +## $ qemu-img create -f raw disk.img 10G +## $ sudo mkfs.{btrfs,ext4,whatever} -F disk.img +$ make qemu +# -> this will build everything and launch QEMU in -nographic mode (output from the serial port). +``` + +Some other options from the given Makefile: + +- Everything is set to be quiet. If you want to remove that, just set `V=1` when + calling any make target. +- If you pass `DEBUG=1`, then further debug messages will be shown. +- The value being passed to GCC's `-march` is the one that matches my + VisionFive2 board. If you want to tune this differently, simply set + `ISA=` on any make target. + +## Architecture + +Still in the works but something like: + +- zsbl -> opensbi -> kernel -> init +- init: + - poll and, for each incoming HTTP request (using io_uring): + - clone with proper flags (with control for fork-bombs) + - http parser + - Database with either embedded sqlite or plain dirs/files. + - reply back with htmx + +### Alternatives + +#### Rust + +I actually considered building this with Rust, but since I figured I would be +doing a lot of interfacing with libraries from the Linux kernel, then I'd also +need to work on safe abstractions for all that C code. Since I didn't want to do +any of that for this project, I just sticked with C. + +#### nolibc et. al. + +I tried to work with `nolibc` as integrated from the Linux kernel, but then I +couldn't build the whole thing because of `-Werror` and the fact that `nolibc` +is riddled with a diverse set of warnings. Hence, maybe in the future I add a +way to support this, but for now it's good ol' `glibc`. + +## License + +Released under the [GPLv3+](http://www.gnu.org/licenses/gpl-3.0.txt), Copyright +(C) 2024-Ω Miquel Sabaté Solà. -- cgit v1.2.3