1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2024-11-29 18:29:40 +02:00

Add page about inline assembly.

This commit is contained in:
Andrew Walbran 2023-03-20 18:00:29 +00:00
parent f293ede958
commit 8b21f5070e
5 changed files with 92 additions and 9 deletions

View File

@ -256,6 +256,7 @@
# Bare Metal Rust: Afternoon
- [Application processors](bare-metal/aps.md)
- [Inline assembly](bare-metal/aps/inline-assembly.md)
- [MMIO](bare-metal/aps/mmio.md)
- [Let's write a UART driver](bare-metal/aps/uart.md)
- [More traits](bare-metal/aps/uart/traits.md)

View File

@ -14,10 +14,6 @@ spin = "0.9.4"
[build-dependencies]
cc = "1.0.73"
[[bin]]
name = "minimal"
path = "src/main_minimal.rs"
[[bin]]
name = "improved"
path = "src/main_improved.rs"
@ -25,3 +21,11 @@ path = "src/main_improved.rs"
[[bin]]
name = "logger"
path = "src/main_logger.rs"
[[bin]]
name = "minimal"
path = "src/main_minimal.rs"
[[bin]]
name = "psci"
path = "src/main_psci.rs"

View File

@ -12,26 +12,30 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: build qemu_minimal qemu qemu_logger
.PHONY: build qemu qemu_logger qemu_minimal qemu_psci
all: minimal.bin improved.bin logger.bin
build:
cargo build
minimal.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/minimal $@
improved.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/improved $@
logger.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/logger $@
minimal.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/minimal $@
psci.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/psci $@
qemu_minimal: minimal.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s
qemu: improved.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s
qemu_logger: logger.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s
qemu_minimal: minimal.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s
qemu_psci: psci.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s
clean:
cargo clean

View File

@ -0,0 +1,51 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ANCHOR: main
#![no_main]
#![no_std]
use core::arch::asm;
use core::panic::PanicInfo;
mod exceptions;
const PSCI_SYSTEM_OFF: u32 = 0x84000008;
#[no_mangle]
extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {
// Safe because this only uses the declared registers and doesn't do
// anything with memory.
unsafe {
asm!("hvc #0",
inout("w0") PSCI_SYSTEM_OFF => _,
inout("w1") 0 => _,
inout("w2") 0 => _,
inout("w3") 0 => _,
inout("w4") 0 => _,
inout("w5") 0 => _,
inout("w6") 0 => _,
inout("w7") 0 => _,
options(nomem, nostack)
);
}
loop {}
}
// ANCHOR_END: main
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}

View File

@ -0,0 +1,23 @@
# Inline assembly
Sometimes we need to use assembly to do things that aren't possible with Rust code. For example,
to make an <abbr title="hypervisor call">HVC</abbr> to tell the firmware to power off the system:
```rust,editable,compile_fail
{{#include examples/src/main_psci.rs:main}}
```
(If you actually want to do this, use the [`psci`][1] crate which has wrappers for all these functions.)
<details>
* PSCI is the Arm Power State Coordination Interface, a standard set of functions to manage system
and CPU power states, among other things. It is implemented by EL3 firmware and hypervisors on
many systems.
* The `0 => _` syntax means initialise the register to 0 before running the inline assembly code,
and ignore its contents afterwards. We need to use `inout` rather than `in` because the call could
potentially clobber the contents of the registers.
</details>
[1]: https://crates.io/crates/psci