ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to #rust-embedded:matrix.org and logged at https://libera.irclog.whitequark.org/rust-embedded, code of conduct at https://www.rust-lang.org/conduct.html
Foxyloxy has quit [Read error: Connection reset by peer]
sroemer has joined #rust-embedded
sroemer has quit [Changing host]
sroemer has joined #rust-embedded
rainingmessages has quit [Quit: bye]
_whitelogger has joined #rust-embedded
sroemer has quit [Quit: WeeChat 4.5.2]
sroemer has joined #rust-embedded
sroemer has joined #rust-embedded
sroemer has quit [Changing host]
_whitelogger has joined #rust-embedded
sroemer has quit [Read error: Connection reset by peer]
sroemer has joined #rust-embedded
sroemer has quit [Changing host]
sroemer has joined #rust-embedded
pcs38 has joined #rust-embedded
ben[m] has quit [Quit: Idle timeout reached: 172800s]
bitts[m] has quit [Quit: Idle timeout reached: 172800s]
<thejpster[m]> Should we require Exception Handlers in cortex-ar to be unsafe if they can control where execution resumes?
<thejpster[m]> they are not unsafe to call (they may just print a message and return an integer, which is totally safe), but when called by the ASM exception handlers, the choice of returned value can very easily lead to UB.
<whitequark[cis]> i think that if you wanted to do this in a rigorous way, you would make the function safe, but the return value a newtype around usize which is unsafe to construct
<whitequark[cis]> and which is also passed as an argument (modulo that i don't know aarch64 semantics enough to know if you have a choice of arg or arg+4, or if it's essentially fixed per exception handler)
<whitequark[cis]> in my opinion the semantic you describe translates to, essentially, "the function must require unsafe { return ...; }" but that's not really a thing in rust, and what i'm suggesting is the next closest thing
<whitequark[cis]> you could also make the function `-> !` and have a function/macro with a bit of inline assembly that does the actual return that would be unsafe to call and required in lieu of falling off the end or a `return` statement
<whitequark[cis]> from my experience with other architectures, I would lean toward the former since it allows writing entirely safe exception handlers by passing in the !Clone newtype as a token and then requiring it back as a return value, which you can't do with a exception_return!(addr) macro. it's also conceptually a bit simpler than a macro, i think
korbin[m] has quit [Quit: Idle timeout reached: 172800s]
<JamesMunns[m]> I don't really have any context, but "you need a type that is unsafe to create to return" from a function seems like a really neat trick.
<JamesMunns[m]> It would also mean you could safely define a handler that diverges with `!`
<JamesMunns[m]> real hotel california approach to safety
<whitequark[cis]> (hotel california?)
<JamesMunns[m]> "you can check in any time you like, but you can never leave"
<JamesMunns[m]> (it's a song by the Eagles)
<whitequark[cis]> <JamesMunns[m]> "I don't really have any context,..." <- i use these types of tricks a lot; they are natural to me because i think of rustc as an automated proof assistant. in this case i request the programmer to prove they have discharged their obligations by presenting a witness value
<JamesMunns[m]> yep! totally makes sense, it's just not a trick I'd seen before, and I'm definitely going to remember it :D
<whitequark[cis]> but i also see a lot of people just go for "make the thing unsafe" when this doesn't actually prevent the unsafety from happening and it confuses me a bit, i guess just because i have a different context and am familiar with different approaches
<JamesMunns[m]> ive seen it on ENTRY to a function, critical section tokens work like that. just never on EXIT of a function
<whitequark[cis]> btw, you should also make the token !Send, !Sync since otherwise you could theoretically use one exception handler to stash it somewhere before never returning (exploding or spinning forever) while another exception handler later fetches the token and uses it to cause havok
<whitequark[cis]> nobody would actually do this but the unsoundness of this case bothers me too much to not mention it
<whitequark[cis]> if you put a raw pointer inside that should do the trick
pcs38 has quit [Quit: leaving]
jannic[m] has joined #rust-embedded
<jannic[m]> And make sure that you can't call such a function from rust code: I didn't check, but I guess that calling a function that's `-> !` but that in fact returns using some `asm!` trickery is also UB, as the compiler won't expect that such a function ever returns and there may not be a next instruction to return to.
<jannic[m]> * > you could also make the function -> ! and have a function/macro with a bit of inline assembly that does the actual return
<jannic[m]> And make sure that you can't call such a function from rust code: I didn't check, but I guess that calling a function that's `-> !` but that in fact returns using some `asm!` trickery is also UB, as the compiler won't expect that such a function ever returns and there may not be a next instruction to return to.
dirbaio[m] has joined #rust-embedded
<dirbaio[m]> How's this handled in cortex-m? You can also return from exceptions there
<jannic[m]> You can't (easily) call the exception handlers from rust code IIRC, I don't remember how it was implemented, some name mangling by the exception macro probably.
<jannic[m]> And if the exception handler is called by some actual exception, that's fine: There's never been an actual function call or return from the "caller"'s point of view. It would only be a problem if some rust code manually called such an exception handler.
sroemer has quit [Quit: WeeChat 4.5.2]
adamgreig[m] has joined #rust-embedded
<adamgreig[m]> the cortex-m exception handlers can't change where execution resumes with their return value, unlike the ones proposed in cortex-ar, aiui
<adamgreig[m]> so in cortex-m we need to ensure you don't call the exception handler from rust code (by name mangling as jannic mentioned) but we don't care about being able to return
<adamgreig[m]> there is talk of having HardFault be given an &mut argument that would allow this, though
<thejpster[m]> Yeah I want to let you recover from a faulting instruction by returning to the one after
<thejpster[m]> I could change to to return an enum { TryAgain, SkipIt }
<thejpster[m]> But I didn’t want to rule out returning to arbitrary places, like you might do in an RTOS when it switches tasks.
<thejpster[m]> Also the number of bytes you have to skip is 4 if you faulted on an A32 instruction but 2 (or maybe 4) on a T32 instruction.
<thejpster[m]> I think what I have is ok for a v0.2 and the PR is probably large enough already.
<thejpster[m]> I’d be very happy to see other people contribute ideas here. We have lots of examples that we test in CI so you can refactor fearlessly.
<whitequark[cis]> (wouldn't you need to swap the stack and the context in an RTOS?)
<thejpster[m]> Yes, but you could probably just change the stack pointer and let the normal context restore in the asm trampoline restore a different context.
pcs38 has joined #rust-embedded
pcs38 has quit [Quit: leaving]
Kaspar[m] has joined #rust-embedded
<Kaspar[m]> <thejpster[m]> "Yes, but you could probably just..." <- That's pretty much how RTOSes do the context switch on CortexM. And deal with the high regs that the exception entry/exit doesn't save/restore.
cr1901_ has quit [Read error: Connection reset by peer]
cr1901 has joined #rust-embedded
ivche_ has joined #rust-embedded
ivche has quit [Ping timeout: 272 seconds]
ivche_ is now known as ivche
mathu_ has joined #rust-embedded
boru2 has joined #rust-embedded
Kaspar[m] has quit [*.net *.split]
dne has quit [*.net *.split]
nadja has quit [*.net *.split]
boru has quit [*.net *.split]
mathu has quit [*.net *.split]
jasperw has quit [*.net *.split]
Kaspar[m] has joined #rust-embedded
dne has joined #rust-embedded
jasperw has joined #rust-embedded
nadja has joined #rust-embedded