-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce umode binary and map it in salus user space address. #178
Conversation
24bc469
to
ac2859a
Compare
lds/umode.lds
Outdated
|
||
.stack : ALIGN(4096) { | ||
PROVIDE(_stack_start = .); | ||
. += 4096; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is 4kB going to be enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No but can be changed quite easily. This is just for the stub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, can we put some space between the bss and the stack so that we get a page fault when we inevitably hit that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per inevitably, once we get an actual binary doing something the linking would've been changed.
Updated. Got rid of MEMORY command as it influences the way ld
finds the next available address when assigning a section to a memory region.
Now there's an empty 4k section between the end of BSS and stack.
riscv-elf/src/lib.rs
Outdated
fn as_usize(&self) -> Option<usize> { | ||
self.inner.try_into().ok() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're assuming 64-bit everywhere else in the module, so I don't really see a problem assuming usize == u64
here too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I went for paranoia in this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed. as_usize() returns usize. (with a comment).
src/hyp_map.rs
Outdated
} | ||
|
||
impl HypMap { | ||
/// Create a new hypervisor map from a hardware memory mem map. | ||
pub fn new(mem_map: HwMemMap) -> HypMap { | ||
let regions = mem_map | ||
pub fn new(mem_map: HwMemMap, elf_map: ElfMap) -> HypMap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/elf_map/user_map (or umode_map)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if I have to chose (and not chose elf_map
, i'll go for user_map
. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to user_map.
src/hyp_map.rs
Outdated
// Data to be populated in the VA area | ||
data: Vec<u8>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we avoid this extra memcpy()
from the ELF to this temporary buffer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're describing my Thursday night. Originally I had kept the reference from 'elf
to here. It is sane because afterall the elf is 'static
. But turns out that at least I couldn't understand how to let Rust understand in a non convoluted way that there were to lifetimes here, one of the underlying data structure and the other of the user_map
.
In general the structure needs to have a life time, the code becomes much much harder to follow and should essentially hold the ElfMap in it to keep the reference lifetime valid. Just over complication for a language that clearly doesn't like these sort of things.
This would also remove generality to the whole concept of a populated region.
In general, much more complicated code, to save a few kbs of RAM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you had your lifetimes backwards in ElfMap::segments()
. With that fixed, this becomes pretty straightforward, see https://github.com/abrestic-rivos/salus/tree/for-glg/user_mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whops. That's a few hours of my life I'll never get back. Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to your code. Thanks again.
@@ -459,8 +449,34 @@ extern "C" fn kernel_init(hart_id: u64, fdt_addr: u64) { | |||
let guest_phys_size = mem_map.regions().last().unwrap().end().bits() | |||
- mem_map.regions().next().unwrap().base().bits(); | |||
|
|||
// Parse the user-mode ELF containing the user-mode task. | |||
let user_elf = include_bytes!("../target/riscv64gc-unknown-none-elf/release/umode"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh, this is gross but I don't immediately have a better suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is indefensible but also the best thing we can do now. Double-checked with @dgreid about this as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it's just a hack until we figure out a better build system. I'm hoping to let zach and tom figure out blaze for hubris tasks then copy that.
ac2859a
to
bb182f4
Compare
bb182f4
to
7bef103
Compare
Simplified |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
libuser/src/task_start.S
Outdated
la t1, task_main | ||
la ra, 1f | ||
jr t1 | ||
|
||
j 1f | ||
1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call task_main
is sufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good catch. Had a note somewhere when I saw your patches to change this too. Thanks!
Fixed.
lds/umode.lds
Outdated
|
||
.stack : ALIGN(4096) { | ||
PROVIDE(_stack_start = .); | ||
. += 4096; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, can we put some space between the bss and the stack so that we get a page fault when we inevitably hit that case?
This patch introduces stub userspace binary and library for salus. Currently the code is compiled but unused. Original code by Dylan, with minor changes from me. Signed-off-by: Dylan Reid <[email protected]> Signed-off-by: Gianluca Guida <[email protected]>
ca212f7
to
e8a264c
Compare
Added a fix to load Program Headers that have no data in file. |
riscv-elf is a library to parse an elf file in memory in Rust. It is esplicitly tailored to salus and riscv. Work has been done (mainly through fuzzing) to check that the library can handle malformed ELF functions. It is a simple library focused on loading an elf. Its main use is to return an `ElfSegment` iterator that mirrors the Program Header section and its data content. Signed-off-by: Gianluca Guida <[email protected]>
Signed-off-by: Gianluca Guida <[email protected]>
This patch allows to map the `umode` binary into salus address space. More work might be needed for a better build system and integration of the umode binary into salus. Signed-off-by: Gianluca Guida <[email protected]>
e8a264c
to
2be9b68
Compare
This PR includes a
umode
andlibuser
library (taken from Dylan's branch). These are just stubs at the moment, but they do create a risc-v elf binary that can be used as a basis for future userspace work.It also introduces riscv-elf. A super simple ELF library tailored to our needs, with no memory allocation and focused on loading elf. Care has been taken in checking the validity of file offset before accessing them.
It then proceed to extend
HypMap
to allow a new type of region to be loaded. Specifically, it's a region that needs to be allocated and populated with existing data.With this patch, the ELF is loaded in userspace, and there's a copy of the whole elf for each CPU. Current abstraction can be changed though to share
.text
and.rodata
across CPUs. Although the big batch of memory (.data
and.stack
) will always be per-cpu.