-
Notifications
You must be signed in to change notification settings - Fork 78
Add boot_argument(), returns the value an a*
register had at boot time
#94
Conversation
This unconditionally reserves 8 * XLEN in |
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.
this seems sensible to me. I'll wait for @Disasm to approve as well tho.
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.
This will not work well in multi-core environments since multiple cores will execute the same code at the same time. If different argument values are passed on different cores, we will get garbage in the end.
I checked binary sizes and this PR adds 44 bytes of code for |
This avoids a data race on multicore
I’d added a branch on hartid that I believe should fix the multicore issue. What does the source code look like for passing to main in your comparison? |
I created a draft PR for this: #95. |
STORE a5, 5*REGBYTES(t1) | ||
STORE a6, 6*REGBYTES(t1) | ||
STORE a7, 7*REGBYTES(t1) | ||
fence rw, rw |
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’m not confident about this (single) fence, or about using plain reads in fn boot_arguments
.
At first I started emulating the behavior of AtomicUsize
: https://rust.godbolt.org/z/3djWjhPcG. But why is the fence
instruction placed before stores and after loads? I’d expected fences to be between things in order to separate them.
On the Rust size I ended up with this, since AtomicUsize
is disabled on targets without the A
extension. The portable-atomic
crate would be another option for doing the same.
/// Simulate AtomicUsize::load(Ordering::Acquire)
unsafe fn atomic_load(ptr: *const usize) -> usize {
let value;
// Only lw v.s. ld changes but asm! wants a string literal
#[cfg(target_pointer_width = "32")]
core::arch::asm!(
"fence r, rw",
"lw {value}, 0({ptr})",
ptr = in(reg) ptr,
value = out(reg) value,
);
#[cfg(not(target_pointer_width = "32"))]
core::arch::asm!(
"fence r, rw",
"ld {value}, 0({ptr})",
ptr = in(reg) ptr,
value = out(reg) value,
);
value
}
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.
Position of fence instructions depends on the ordering. With SeqCst
you get fences before and after the load.
Closing in favor of #95 |
Fixes #92
With this PR, the code below succeeds in QEMU and
Fdt
can be used to find the address of the simulated UART that prints to stdout on the host.