Skip to content

SWI / SVC support #265

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

Open
thejpster opened this issue Sep 4, 2020 · 8 comments
Open

SWI / SVC support #265

thejpster opened this issue Sep 4, 2020 · 8 comments

Comments

@thejpster
Copy link
Contributor

Could we add intrinsics for calling Software Interrupts (the SWI or SVC instruction)? We probably also want a mechanism for marshalling some number of integer arguments into registers, and back out again on the other side of the SWI (i.e. in the kernel).

TockOS do this with llvm_asm!, as you can see at https://github.com/tock/tock/blob/198ff4173e85f6b8474893c6784d38c12ead9dbb/arch/cortex-m0/src/lib.rs#L161

@jonas-schievink
Copy link
Contributor

As described in #58, this is not in general possible since the specific svc ABI depends on the environment

@thejpster
Copy link
Contributor Author

Ah. I guess it would be unreasonable to have an array of 256 function pointers to let you pick the SVC value...

@jonas-schievink
Copy link
Contributor

Once inline assembly is stable, we can provide a const-generic function like this:

fn svc<const NUM: u8>() {
    unsafe {
        asm!("svc {imm}", imm = const NUM);
    }
}

@thejpster
Copy link
Contributor Author

Once inline assembly is stable, we can provide a const-generic function like this:

fn svc<const NUM: u8>() {
    unsafe {
        asm!("svc {imm}", imm = const NUM);
    }
}

Nice!

@thejpster
Copy link
Contributor Author

So reading around a bit on this, some syscall ABIs just set the SVC value to be zero, as it's expensive to pull it out on the receiving side (you have to read the instruction that caused the interrupt, which will be in a different cache...). So, could we at least have a function which lets you SVC 0, and optionally populate some registers with arguments.

adamgreig pushed a commit that referenced this issue Jan 12, 2022
265: link.x: .bss should be NOLOAD r=japaric a=cbiffle

Previously, this linker script was producing an ELF PHDR marked LOAD for
the .bss section, which suggested to tools like OpenOCD that something
needed to be copied into RAM during flashing. This section happened to
have filesz=0 in practice, so only extra bookkeeping work was done and
not extra transfers. We noticed this when tracking down an odd behavior
in one of our ELF post-processing tools.

With this change, the linker script no longer emits a LOAD PHDR.

Co-authored-by: Cliff L. Biffle <[email protected]>
bors bot added a commit that referenced this issue Mar 1, 2022
423: Swap to just-stabilised asm!() and global_asm!() macros r=thejpster a=adamgreig

Once Rust 1.59 is released in a couple of days, the `asm!()` and `global_asm!()` macros will become stable, and we will no longer require the various precompiled binaries we've used until now in cortex-m and cortex-m-rt. cc #420.

This PR uses `asm!()` in cortex-m, and removes the inline-asm feature, since I anticipate this going into cortex-m 0.8 and so we don't need to leave it behind for compatibility. In various places the previous version would call an extern C method when built for the native target, which would only fail at link time; to preserve the ability to build on x86 I've either made the whole method require the `cortex_m` configuration, or where appropriate/convenient simply skipped the `asm!()` call.

This PR replaces the old gcc-preprocessed `asm.S` in cortex-m-rt with use of `global_asm!()`, although since you can't normally use `#[cfg(...)]` attributes with `global_asm!()`, there's also a slightly scary macro modified from one invented by `@Dirbaio` for a similar purpose. I considered putting the initialisation of LR behind an armv6m flag, but since we want to restore it after calling `__pre_init` it seemed better to just leave it the same on both targets. I added Cargo features to optionally set SP and VTOR at startup, which has been variously requested but would previously have required multiplicatively more pre-built binaries. Now: no problem. Relevant issues:

* rust-embedded/cortex-m-rt#283
* rust-embedded/cortex-m-rt#55
* rust-embedded/cortex-m-rt#254
* rust-embedded/cortex-m-rt#102
* rust-embedded/cortex-m-rt#338

I've tested these on a couple of targets (and updated the CI): on the whole there's a small improvement in code size due to everyone getting inlined asm, especially in `cortex_m::interrupt::free()`.

The major downside is we bump our MSRV from 1.42 (March 2020) to 1.59 (Feb 2022). For cortex-m, I propose putting these changes in the upcoming 0.8 release (which is technically what the master branch is already on) and not backporting. For cortex-m-rt I'm not sure: we don't have any other pending breaking changes, so we could consider a patch release. Anyway, this PR doesn't commit to any particular releases, so we can decide that later.

For cortex-m-semihosting/panic-semihosting I think a patch release would be ideal, especially since we had to yank the last c-m-sh release due to conflicting prebuilt binaries (a problem that should now vanish).

Also tagging these issues that I think might also benefit from new inline asm:
* #265
* #215
* #406

Co-authored-by: Adam Greig <[email protected]>
@jamesmunns
Copy link
Member

Just tagging this issue as I've hit this as well, and we now have stable asm.

That being said, I'm probably also just going to go the "svc 0" route as well.

@adamgreig
Copy link
Member

I guess we'll want https://doc.rust-lang.org/unstable-book/language-features/asm-const.html for this one.

@korken89
Copy link
Contributor

korken89 commented Feb 5, 2025

Seems to be working now :)
https://rust.godbolt.org/z/fPK5Mh5sz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants