Where to start with a hobby OS

So I have a semester of programming experience with XV6 (MIT’s RISC-V teaching OS) and I bought the HiFive board with the sole purpose of getting what I worked on to boot on physical hardware.
However all my development experience has been with QEMU and as I understand the memory mapping will be different, but what other things do I need to look out for?

Also how would I format the SD Card. I assume this is dependent on the boot loader?

Sorry for being all over the place, but I think I bit off a bit more than I can chew.

For now my goal is to get something to boot where I can some something on the UART terminal.

xv6 should be able to work.

It does really minimal setup in M mode before switching to S mode. So it needs to be loaded and run while still in M mode. I’m not sure that is optimal for porting. It would probably be better if it could run on top of standard OpenSBI, on both qemu and various boards.

It would be very cool if someone sets up an SD card image that can just be downloaded and burned and run.

For linux, a guide to building it from source can be found here.
This talks a bit about the boot loader opensbi/u-boot and how to set up the sdcard. You would probably want something similar except replace the linux partition with xv6. This assumes it can run on top of opensbi though.

It currently can’t. It starts from machine mode and use fixed MMIO registers of QEMU virt machine. SBI is not used.

You can use the u-boot command line to load files into memory at a specified address and then execute them. It’s pretty powerful. You’ll probably want to load to 0x80000000 and execute in machine mode.

After that if you want to automate boot you’ll then want to do u-boot menuconfig to set it up as you wish, compile, and burn your boot loader.

I have a toy OS written in rust that I plan to do the same thing with, but I admit I’m still bogged down on something else (trying to get linux to boot with root file system on nvme without an initrd)

Does it support running loaded code in machine mode?

Anyway it will not run without changes, it use VirtIO disk and incompatible UART.

It’s running OpenSBI in M mode, I don’t see why it wouldn’t run anything else in M mode. If I get a chance I’ll post details. I really do need to get my toy project running on real hardware anyways.

Without u-boot there is a lot of board setup you might get bogged down in. See the https://sifive.cdn.prismic.io/sifive/18febb04-50b6-4880-9bf3-631e40daa809_fu740-c000-manual-v1p2.pdf manual section 6.3. This is all done by u-boot: setting frequency PLLs, waiting for them to spin up, configuring DDR, PHY, reading from the SD card and parsing partition data, getting the next bit of code loaded, enabling the L2 to use DDR for 15/16 ways, jumping to 0x8000_0000 (and other stuff).

I’m not sure, but it might be possible to break your hardware in M mode, since it’s very low level. I’d be interested to know this.

You’ll need to write a driver to access the MMC SDCard, or else for both the PCIe and NVME, or else for usb/*hci… if you want any storage at all. Those will need clock drivers and other associated drivers.

The SiFive UART is quite easy to program. If you’ve already got spinlocks and interrupt handling it should be straightforward. It would be even easier if you could use atomics on I/O memory, but alas that’s apparently not a thing (dead end I went down about a month ago).

@ mikedilger Thank you for the detailed response! I really appreciate it.

Yeah the hardest part about this to me the boot process currently, and I haven’t started to find all the memory mappings that I will need to replace in memlayout.h. I checked out the manual and all the initializations seem complicated and I’d rather avoid them for now. I’ll

Thanks for the clarification about the MMC SDCard, I’ll eventually write a driver for it, but I think I’ll just try and figure out a solution like the kernelmemfs option the x86 variant of XV6 has, so I won’t have to worry about the disk for now. However it would be nice to forgo even that for now for testing the boot sequence; I’ll have to check the feasibility of that, it probably involes just stripping all the disk access code.

I’m glad to hear that the UART system is easy to implement.

Also I’d love to check out your toy project, especially if you get it to boot.

@X512 thank you for the input. I have seen the work you have done for the Haiku project and I think it is really amazing and impressive how much you have accomplished. You are definitely someone I look up to.

The flow is U-Boot SPL (M-mode) → OpenSBI (M-mode) → U-Boot (S-mode). U-Boot SPL is U-Boot in name only, it’s low-level platform firmware that does grotty initialisation (DRAM training, enabling caching, flipping vendor feature bits in CSRs, etc) and has just enough code to load the OpenSBI+U-Boot next stage bundle. It just happens to be in the same repository as U-Boot and use some common code (but not much, it’s a minimal binary). There is no way to inject yourself in the process as M-mode code without building a custom version of U-Boot SPL and/or OpenSBI.

This is all U-Boot SPL, not the real U-Boot. The distinction is important.

You can certainly fail to set up the overheating protection properly and fry your chip that way. I wouldn’t be surprised if incorrectly programming the memory controller during training also can fry either the core or DRAM.

Whether or not atomics work on I/O memory is up to the platform; see the “Physical Memory Attributes” section of the RISC-V privileged spec. In the case of SiFive’s cores, you can absolutely use atomics on the UART, and that’s what BBL does, though not OpenSBI curiously (probably because neither does Linux). Table 15 in the FU740 manual has “a” in the UART rows to indicate this. The documentation for the UART itself even says:

A RISC‐V amoor.w instruction can be used to both read the full status and attempt to enqueue data, with a non-zero return value indicating the character was not accepted.

1 Like

Great stuff @jrtc27 .

Now that you mention it, yeah it wasn’t atomics in general that I had to back up on, it was LR/SC not having a completion guarantee.

Awesome response jrtc27

Considering the hardware damage implications, I think I’ll try and use U-Boot as intended for XV6 which means I need to implement OpenSBI then. It looks like I’ll have to do a deep dive on U-Boot and OpenSBI.

Maybe I should start off with writing something very simple for U-Boot to load like a simple hello world message or something over UART. Or is there something more simple?

OpenSBI is already implemented for HiFive Unmatched. You could modify XV6 to use OpenSBI instead of the small amount of M mode code it has now. Or you can just use the M mode part of U-Boot and replace OpenSBI with XV6.

Portability to other RISC-V boards will be better if you get XV6 to run on top of standard OpenSBI. That’s the point of the SBI – the Linux kernel for example is intended to run unchanged on every RISC-V board, with SBI having the machine-dependent parts.

Of course you then need the appropriate device drivers to load into (or build into) your OS kernel.

In this guide,I have some problem when build u-boot,I use latest released version with Unmatched patches until they get upstreamed.
$ for f in …/meta-sifive/recipes-bsp/u-boot/files/unmatched/*.patch; do echo $f;patch -p1 < $f;done

problem is

Are there “drivers” and “board” directories in the place you are cd to?

there are drivers” and “board” directories in the place,
and when “vi arch/riscv/dts/fu740-c000-u-boot.dtsi”,
I can not find fu740-c000-u-boot.dtsi in this directory
I do not know the reason,can you help me :+1:

I think you have meta-sifive and u-boot versions confused. Old versions of meta-sifive have patches for u-boot v2021.01. New versions of meta-sifive have patches for u-boot v2021.07. So it looks like you are trying to apply patches for u-boot v2021.07 to u-boot v2021.01 which won’t work. You need consistent versions of meta-sifive and u-boot. If you really need u-boot v2021.01 then you need to use an older version of meta-sifive. If you want to use the current version of meta-sifive, then you need to use u-boot v2021.07.

Running ls in the meta-sifive/recipes-bsp/u-boot dir will show you what u-boot version these patches are for, as the u-boot version is encoded in some of the filenames.

As you said,my problem is solved. Thank you very much~
there is another problem,I can not find this file :sifive_hifive_unmatched_fu740_defconfig
when do :CROSS_COMPILE=riscv64-unknown-linux-gnu- make sifive_hifive_unmatched_fu740_defconfig
can you please tell me the reason?

It’s been changed to CROSS_COMPILE=riscv64-unknown-linux-gnu- make sifive_unmatched_defconfig

riscv-bringup/unmatched at master · carlosedp/riscv-bringup · GitHub needs to be updated with the latest U-Boot and patches instructions.

OK thank you very much for your reply
then where can I find the newest guide