Page MenuHomeFreeBSD

[RISC-V] Set ra to zero when calling into userspace
AcceptedPublic

Authored by arichardson on Aug 21 2024, 5:29 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Nov 25, 6:10 PM
Unknown Object (File)
Mon, Nov 25, 2:33 PM
Unknown Object (File)
Sat, Nov 23, 2:27 AM
Unknown Object (File)
Tue, Nov 19, 10:39 AM
Unknown Object (File)
Wed, Nov 13, 6:50 PM
Unknown Object (File)
Fri, Nov 8, 10:33 PM
Unknown Object (File)
Fri, Nov 8, 12:13 AM
Unknown Object (File)
Oct 16 2024, 3:30 PM
Subscribers

Details

Reviewers
jrtc27
jhb
Group Reviewers
riscv
Summary

This ensures that the return address observed by pthread_create is
zero and therefore libunwind does not continue unwinding beyond the
start of the thread (which previously would result in crashes).

This fixes the LLVM libunwind thread_unwind.pass.cpp test.

See the equivalent https://reviews.freebsd.org/D40841 for AArch64.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 59130
Build 56017: arc lint + arc unit

Event Timeline

Should we also do fp/s0 to match, like arm64 does?

Should we also do fp/s0 to match, like arm64 does?

That probably makes sense as well - IP==0 is sufficient to stop but might as well tell it that the stack is also gone after this point. Not sure what Linux does here or if there is any document that mandates this behaviour.

sys/riscv/riscv/vm_machdep.c
182

I thought the initial tf was zeroed though? I guess we copy it above in cpu_copy_thread. We really only want the copy for fork(). For thr_new() the tf should generally be zero'd IMO. That is, I wonder if you could just do memset(tf, 0, sizeof(*tf) before the assignment to tf_sp?

sys/riscv/riscv/vm_machdep.c
182

PowerPC does it that way, I don't think other architectures do. You'd need to initialise tf_sstatus in that case though, and userspace has the expectation that tf_gp is preserved, since that's done in userspace at process startup only.

sys/riscv/riscv/vm_machdep.c
182

As far as I can tell when called from thr_new, the registers are preserved. I'd be fine with starting threads with a well defined zeroed state but not sure if anything relies on this behaviour of preserving registers (I'd hope not...).

If we zero everything we probably need to do it for all architectures, but I don't have the time to test that :(

sys/riscv/riscv/vm_machdep.c
182

Hmm, maybe we should preserve those two fields and zero everything else?

This is fine for now. I do think long term we want to figure out the minimum set of registers to preserve for each arch and zero the rest.

This revision is now accepted and ready to land.Sep 30 2024, 2:30 PM