diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-12-05 15:34:33 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-12-05 16:02:51 +0100 |
| commit | 76169cd214e4830a523c8c2ee7bbddc04b4253df (patch) | |
| tree | 54d754426ca41729414e7f7ddb9427a61594f464 /arch/riscv/supervisor/hsm/README.md | |
| parent | f463d544793ff83efd8b95d0bce5ec80fd8170f3 (diff) | |
| download | farga-76169cd214e4830a523c8c2ee7bbddc04b4253df.tar.gz farga-76169cd214e4830a523c8c2ee7bbddc04b4253df.zip | |
supervisor: Add an example on the HSM extension
The HSM extension from SBI v2.0 allows a supervisor to manage the state
of harts on the system. Moreover, it also guarantees that only one hart
makes it into the booting stages of the supervisor, and it's up to the
supervisor to wake up the rest through the HSM extension.
I have added an example which showcases this extension in different
ways, and it finally shuts down the machine.
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'arch/riscv/supervisor/hsm/README.md')
| -rw-r--r-- | arch/riscv/supervisor/hsm/README.md | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/arch/riscv/supervisor/hsm/README.md b/arch/riscv/supervisor/hsm/README.md new file mode 100644 index 0000000..a950152 --- /dev/null +++ b/arch/riscv/supervisor/hsm/README.md @@ -0,0 +1,126 @@ +# Messing with the Hart State Management Extension ("HSM") from the SBI + +This is a simple kernel that messes with the HSM Extension from the SBI v2.0. In +general, and according to the RISC-V specification, harts can enter Supervisor +mode at any time. This makes thing simple both for the RISC-V specification and +machines implementing the architecture. For the kernel this means that you never +know which hart is going to start first, and in cases like the Linux kernel, you +actually want to ensure that only one hart is running for initialization +purposes before waking up the rest. In order to guarantee this, the Linux kernel +runs a lottery. + +To run a lottery on this context means that the first hart to appear will +actually take a lock in the kernel, which will block any other "secondary" hart +that appears later. This lock is going to be released once the "main" hart +guarantees that the kernel has been initialized up to a point where other harts +can come in. This lock is implemented with an atomic variable that holds how +many harts have been seen (hence, the first hart will read a zero value from +this variable, and the rest will read a non-zero one). + +All of that being said, the SBI specification v2.0 comes with a cleaner +approach: the HSM extension. With this extension a Supervisor will be able to +manage the state of any hart of the system, which is either `started`, `stopped` +or `suspended` (plus transition states). Moreover, there is the guarantee that +only one hart will be initialized with the `started` state, whereas the rest +will be on `stopped`. This means that a kernel can drop the whole idea of a +lottery and have the guarantee that only one hart will run on start. Whenever +the kernel has been initialized to a specific stage, it will be able to change +the state of the rest of harts to `started`. + +## This example + +This example uses the HSM extension but it also keeps the idea of a lottery. +That is, the first hart will "acquire" the lock ("win" the lottery), and will be +responsible for bringing the rest up. At first this hart will simply print +information on the system. For example, on a system with four harts you will get +something like: + +``` +Hello, world! +Hart that won the lottery: 1 +Harts still asleep: 0, 2, 3 + +How many harts have _participated_ in the lottery? 1 +How many harts have _failed_ in the lottery? 0 +``` + +In this example, only one hart is available: one that "won" the lottery, and the +rest have not even appeared. The hart with ID '1' will be responsible for waking +up '0', '2' and '3'. After making some initial checks, it will wake up the first +secondary hart (no reason to just wake up one, just doing it this way for the +show): + +``` +Waking up first secondary hart +How many harts have _participated_ in the lottery? 2 +How many harts have _failed_ in the lottery? 1 +``` + +Now two harts are available, but the one that woke up is a "secondary" one, so +it lost the lottery and is stuck in `head.S` on an infinite loop doing nothing. +After doing that, the main hart will wake up the rest: + +``` +Waking up the rest +How many harts have _participated_ in the lottery? 4 +How many harts have _failed_ in the lottery? 3 +``` + +Now all four harts are up, but three of them (the "secondary" ones) are simply +stuck in an infinite loop since they have "lost" the lottery. At this point this +example does something weird for a kernel: it will return from the main +function. Doing so allows `head.S` to count the main hart as a "failed" one, and +it will print some final messages for it: + +``` +Goodbye, cruel world! +How many harts have _participated_ in the lottery? 4 +How many harts have _failed_ in the lottery? 4 + +THE END +``` + +At the point where "THE END" is printed, we will then perform an SBI call to the +System Reset Extension ("SRST") to gracefully shutdown the system. + +## Test + +To test this yourself you need a recent enough QEMU which is able to run as a +RISC-V system, and you need to set the `CROSS_COMPILE` environment variable as +you would on the Linux Kernel if you are doing this on a non-RISC-V machine. +After that, you can simply run `make` to build the binary, or simply run `make +qemu` to both build it and run QEMU. + +Notice also that the Makefile accepts the `CPUS` variable, which by default is +set to 4. Change this variable to something else to get a different number of +harts on the example (but lesser than 10, since I haven't bothered to account +for that when printing numerical values). For example, `make qemu CPUS=8`: + +``` shell +Hello, world! +Hart that won the lottery: 5 +Harts still asleep: 0, 1, 2, 3, 4, 6, 7 +How many harts have _participated_ in the lottery? 1 +How many harts have _failed_ in the lottery? 0 + +Waking up first secondary hart +How many harts have _participated_ in the lottery? 2 +How many harts have _failed_ in the lottery? 1 + +Waking up the rest +How many harts have _participated_ in the lottery? 8 +How many harts have _failed_ in the lottery? 7 + +Goodbye, cruel world! +How many harts have _participated_ in the lottery? 8 +How many harts have _failed_ in the lottery? 8 + +THE END +``` + +## Rationale + +This example came after exploring the topic of SMP on +[fbos](https://github.com/mssola/fbos). Even if in there I did not explore this +extension further (because of the needs of the project), I decided that I wanted +a fresh simple kernel to mess with this extension. And hence this project. |
