- Michael Engel (michael.engel@uni-bamberg.de)
- Timo Renk (timo.renk@stud.uni-bamberg.de)
- Fabian Adam (fabian-david.adam@stud.uni-bamberg.de)
- Leonhard Kohn (leonhard.kohn@stud.uni-bamberg.de)
- Tobias Treuheit (tobias-niklas.treuheit@stud.uni-bamberg.de))
- Max Meidinger (max_meidinger@stud.uni-bamberg.de)
- Ibrahima Sory Sow (ibrahima-sory.sow@stud.uni-bamberg.de)
In this project, we attempt to build a mikrokernel in RUST on a RISCV processor. For this we use the code of Timo Renk as a basis.
To run the code, the following is needed:
- gdb-multiarch or riscv-elf-gdb
- rust with rustup and cargo
- qemu for riscv
Once all the required tools are installed, the project can be compiled and run using the provided tasks (Shortcut Strg+Alt+R
).
- Use
Build riscv_rust_os
to build the binaries for the kernel. - Use
Build user binaries
to build the binaries for the user processes to be run - Finally, use
Debug riscv_rust_os
to fire up qemu with the compiled kernel
Now qemu is running with the given binary! But in orderr to get anything from the emulator, the visual studio debugger needs to connect to the debug server.
How to connect to the server is already set up in launch.json, so simply pressing F5
should suffice to connect to the debug server.
To see what instruction is executed at the moment, you can open the Disassembly View
using the Command Palette (Keyboard Shortcut: F1
).
The following workflow might be a bit excessive for the scale of our project, but adhering to it will help to understand git better and to be more comfortable in its usage.
For a more detailed explanation of mentioned commands address the short explanation of them down below.
You would typically start by creating a new feature branch from the current state of the master branch. The next step would be to iteratively implement the feature. This might require more or less changes and should depending on the number of changes be split into multiple commits. For bigger features this might create a lot of smaller commits.
Each commit should, if possible represent some sort of logical unit, meaning that the changes should serve a common purpose as part of the implementation of the feature.
After implementing the feature, all the changes need to be brought into the master branch.
One way to do this might be to change to the master branch and merge the feature branch into the master branch. This will create a merge commit every time, polluting the history of the master branch with the superfluous merge commits.
This might be avoided by rebasing. One would rebase his feature branch onto the current stage of the master branch, which simply reapplies the changes recorded in the commits on the newer state of the master branch. This might lead to conflicts as merging does, but those conflict will be resolved commit per commit and not with all changes of the feature branch.
The final step is to create a merge request. This should only happen if the feature is well-tested, which in our case probably means testing the feature by hand.
First, you need to push the branch to the remote repository. From there you can create a merge request into the master branch.
Make sure to reference the resolved issue in the title of the Merge Request and assign collaborators on that issue as reviewers, so that they can take a finally look at the proposed changes.
The given merge options can in most cases stay ticked.
Especially the squashing of the commits is quite useful: It squashes all commits of the feature branch together into one with the name of the merge request. This results in a quite nice commit history, consisting of one commit for each issue/feature.
Previously the usage of a integration branch was used, but those are typically used to combine multiple feature branches together to be then tested in combination and integrated as one into the master branch. That is not necessary for our project and really only makes sense for larger-scale projects
Here is a list of useful git commands in the order in which they might be used in a typical workflow.
git clone <upstream-url>
git checkout -b <branchname>
This will create a new local branch with the name <branchname>
. This new branch will initially have the same state as the branch that it was created from.
git status
This command will show a number of things:
- Which branch you are currently on
- whether and by how many commits the remote or the local branches are ahead of each other and whether they diverge
- Which files are staged for commit (in green)
- Which files are not staged for commit (in red)
git add <filepath>
This command will stage all changed files that are included in the given path (recursively!) to be added to the next commit
git reset -- <filepath>
This command will remove all files in the staging area included in the file path.
git commit -m <commitmessage>
This will create a new commit containing all the previously staged changes.
git commit --amend -m <commitmsg>
This will add all currently staged changes to the previous commit. Without the -m
flag followed by a commit message a editor will be opened, in which you can edit the previous commit message.
git push
This will push the locally committed changes to the remote branch. This might not work when there is no branch set up as a remote branch for the local branch, for example when the current working branch is created locally an there is no remote branch tracking the local branch yet.
Using git push -u <remote> <branchname>
will set the upstream branch that should correspond to the local branch. If that branch does not exist yet, it will be created.
<remote>
corresponds to the name of the upstream repository. In our case there will probably be only one defaulting to the name origin
.
<branchname>
is the name of the remote branch that is supposed to be tracking the local branch. Most of the time it makes sense to give it the same name as the local branch.
git fetch
This command fetches the current changes from the remote branch, but does not integrate them into the local state.
git merge
This will try to automatically combine all remote changes that have previously been fetched with the local committed changes. There might, however, be some conflicts when the same file has been edited in different commits. Those will need to be resolved and committed in order to finalize the merge.
git merge <branchname>
If you want to merge another local branch into the working branch you can use this command to merge be branch <branchname>
into the current working branch.
get pull
Combines git fetch
and git merge
into one.
git rebase <branchname>
This will apply and recalculate all changes that have happened since the current working branch diverged from the path given by <branchname>
on top of the current state of <branchname>
.
This might also create conflicts that will need to be resolved.
This is a University Project.
Os written in Rust
- rustup target install riscv64gc-unknown-none-elf
gdb-multiarch/ riscv-elf-gdb
msys2: -> pacman -S mingw-w64-x86_64-toolchain
cargo install cargo-binutils rustup component add llvm-tools-preview
[Register]https://en.wikichip.org/wiki/risc-v/registers https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc#system-reset-extension-eid-0x53525354-srst https://github.com/riscv/riscv-isa-manual/#readme https://github.com/rust-embedded/riscv [Register]
https://osblog.stephenmarz.com/ch0.html https://os.phil-opp.com/ https://github.com/sgmarz/osblog/blob/master/risc_v/src/lds/virt.lds https://github.com/skyzh/core-os-riscv/blob/master/kernel/src/uart.rs https://docs.rust-embedded.org/book/start/qemu.html
UART https://www.lammertbies.nl/comm/info/serial-uart
Check riscv reader for paper info for register infos in first two lectures
https://github.com/riscv/riscv-plic-spec/blob/master/riscv-plic.adoc
- How to avoid race-conditions in UART/ Kernel?
- What is mtval?
- Why align to 16?
ALIGN(4096) tells the linker to align the current memory location (which is 0x8000_0000 + text section + rodata section) to 4096 bytes. This is because our paging system's resolution is 4,096 bytes or 4 KiB.
-
ram AT>ram?
- sdata .sbss
- use wfi?
- Wait for interrupts
- info registers
- gdbtui. Or run gdb with the -tui switch. Or press C-x C-a after entering gdb.
- layout asm
- Press C-x s
- use si ni
- use gdb-multiarch!
- x/100x $sp
- -exec p/x $mepc
readelf -a user_1 | less
Don't use it! https://lldb.llvm.org/use/map.html
Check memory layout
x86_64-w64-mingw32-gcc-nm riscv_rust_os | sort