Skip to content

Commit

Permalink
interrupt: Support Xtensa
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Mar 22, 2023
1 parent c41876e commit af2683c
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .github/.cspell/project-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ docsrs
doctests
DWCAS
endianness
espup
exynos
FIQs
getauxval
Expand Down Expand Up @@ -95,6 +96,7 @@ RAII
rclass
rcpc
reentrancy
rsil
sbcs
seqlock
setb
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ jobs:
persist-credentials: false
- name: Install Rust
run: rustup toolchain add nightly --no-self-update && rustup default nightly
- uses: taiki-e/install-action@v2
with:
tool: espup
- run: |
set -euxo pipefail
sudo apt-get -o Acquire::Retries=10 -qq update && sudo apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends \
Expand All @@ -259,7 +262,10 @@ jobs:
sudo mv "opensbi-${OPENSBI_VERSION}-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin" /usr/share/qemu/opensbi-riscv32-generic-fw_dynamic.bin
sudo mv "opensbi-${OPENSBI_VERSION}-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.elf" /usr/share/qemu/opensbi-riscv32-generic-fw_dynamic.elf
rm -rf "opensbi-${OPENSBI_VERSION}-rv-bin"
- run: espup install
- run: tools/no-std.sh
- run: tools/build.sh +esp xtensa-esp32-none-elf
# - run: tools/no-std.sh +esp xtensa-esp32-none-elf # TODO

miri:
strategy:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
- Provide `AtomicI128` and `AtomicU128`.
- Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float))
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, etc.) (always enabled for MSP430 and AVR, [optional](#optional-cfg-unsafe-assume-single-core) otherwise)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-cfg-unsafe-assume-single-core) otherwise)
- Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485), [`Atomic*::as_ptr`](https://github.com/rust-lang/rust/issues/66893).
- Make features that require newer compilers, such as [fetch_max](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [fetch_min](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_min), [fetch_update](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.
- Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc.
Expand Down Expand Up @@ -113,7 +113,7 @@ See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-a

This is intentionally not an optional feature. (If this is an optional feature, dependencies can implicitly enable the feature, resulting in the use of unsound code without the end-user being aware of it.)

ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension are currently supported.
ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported.

Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this cfg.

Expand Down
1 change: 1 addition & 0 deletions src/imp/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ use arch::atomic;
#[cfg_attr(target_arch = "avr", path = "avr.rs")]
#[cfg_attr(target_arch = "msp430", path = "msp430.rs")]
#[cfg_attr(any(target_arch = "riscv32", target_arch = "riscv64"), path = "riscv.rs")]
#[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")]
mod arch;

use core::{cell::UnsafeCell, sync::atomic::Ordering};
Expand Down
39 changes: 39 additions & 0 deletions src/imp/interrupt/xtensa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Refs:
// - Xtensa Instruction Set Architecture (ISA) Reference Manual https://0x04.net/~mwk/doc/xtensa.pdf
// - Linux kernel's Xtensa atomic implementation https://github.com/torvalds/linux/blob/v6.1/arch/xtensa/include/asm/atomic.h

#[cfg(not(portable_atomic_no_asm))]
use core::arch::asm;

pub(super) use core::sync::atomic;

pub(super) type State = u32;

/// Disables interrupts and returns the previous interrupt state.
#[inline]
pub(super) fn disable() -> State {
let r: u32;
// SAFETY: reading mstatus and disabling interrupts is safe.
// (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions)
unsafe {
// Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled.
asm!("rsil {0}, 15", out(reg) r, options(nostack));
}
r
}

/// Restores the previous interrupt state.
#[inline]
pub(super) unsafe fn restore(r: State) {
// SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`,
// and we've checked that interrupts were enabled before disabling interrupts.
unsafe {
// Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled.
asm!(
"wsr.ps {0}",
"rsync",
in(reg) r,
options(nostack),
);
}
}
1 change: 1 addition & 0 deletions src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ mod fallback;
target_arch = "msp430",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "xtensa",
))]
mod interrupt;

Expand Down
9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
- Provide `AtomicI128` and `AtomicU128`.
- Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float))
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, etc.) (always enabled for MSP430 and AVR, [optional](#optional-cfg-unsafe-assume-single-core) otherwise)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-cfg-unsafe-assume-single-core) otherwise)
- Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485), [`Atomic*::as_ptr`](https://github.com/rust-lang/rust/issues/66893).
- Make features that require newer compilers, such as [fetch_max](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [fetch_min](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_min), [fetch_update](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.
- Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc.
Expand Down Expand Up @@ -105,7 +105,7 @@ See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-a
This is intentionally not an optional feature. (If this is an optional feature, dependencies can implicitly enable the feature, resulting in the use of unsound code without the end-user being aware of it.)
ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension are currently supported.
ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported.
Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this cfg.
Expand Down Expand Up @@ -190,7 +190,7 @@ See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-a
clippy::unreadable_literal,
)]
// asm_experimental_arch
// AVR and MSP430 are tier 3 platforms and require nightly anyway.
// AVR, MSP430, and xtensa are tier 3 platforms and require nightly anyway.
// On tier 2 platforms (powerpc64 and s390x), we use cfg set by build script to
// determine whether this feature is available or not.
#![cfg_attr(
Expand All @@ -199,6 +199,7 @@ See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-a
any(
target_arch = "avr",
target_arch = "msp430",
all(target_arch = "xtensa", portable_atomic_unsafe_assume_single_core),
all(
portable_atomic_unstable_asm_experimental_arch,
target_arch = "powerpc64",
Expand Down Expand Up @@ -314,6 +315,7 @@ compile_error!(
target_arch = "msp430",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "xtensa",
)),
))
)]
Expand All @@ -327,6 +329,7 @@ compile_error!(
target_arch = "msp430",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "xtensa",
)),
))
)]
Expand Down
13 changes: 11 additions & 2 deletions tools/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ is_no_std() {
}

pre_args=()
is_custom_toolchain=''
if [[ "${1:-}" == "+"* ]]; then
if [[ "$1" == "+esp" ]]; then
is_custom_toolchain=1
fi
pre_args+=("$1")
shift
fi
Expand All @@ -131,7 +135,10 @@ else
targets=("${default_targets[@]}")
fi

rustup_target_list=$(rustup ${pre_args[@]+"${pre_args[@]}"} target list)
rustup_target_list=''
if [[ -z "${is_custom_toolchain}" ]]; then
rustup_target_list=$(rustup ${pre_args[@]+"${pre_args[@]}"} target list)
fi
rustc_target_list=$(rustc ${pre_args[@]+"${pre_args[@]}"} --print target-list)
rustc_version=$(rustc ${pre_args[@]+"${pre_args[@]}"} -Vv | grep 'release: ' | sed 's/release: //')
host=$(rustc ${pre_args[@]+"${pre_args[@]}"} -Vv | grep 'host: ' | sed 's/host: //')
Expand All @@ -146,7 +153,9 @@ esac
nightly=''
if [[ "${rustc_version}" == *"nightly"* ]] || [[ "${rustc_version}" == *"dev"* ]]; then
nightly=1
rustup ${pre_args[@]+"${pre_args[@]}"} component add rust-src &>/dev/null
if [[ -z "${is_custom_toolchain}" ]]; then
rustup ${pre_args[@]+"${pre_args[@]}"} component add rust-src &>/dev/null
fi
# -Z check-cfg requires 1.63.0-nightly
# shellcheck disable=SC2207
if [[ "${rustc_minor_version}" -gt 62 ]] && [[ -n "${TESTS:-}" ]]; then
Expand Down
15 changes: 13 additions & 2 deletions tools/no-std.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ bail() {
}

pre_args=()
is_custom_toolchain=''
if [[ "${1:-}" == "+"* ]]; then
if [[ "$1" == "+esp" ]]; then
# shellcheck disable=SC1091
. "${HOME}/export-esp.sh"
is_custom_toolchain=1
fi
pre_args+=("$1")
shift
fi
Expand All @@ -71,13 +77,18 @@ else
targets=("${default_targets[@]}")
fi

rustup_target_list=$(rustup ${pre_args[@]+"${pre_args[@]}"} target list)
rustup_target_list=''
if [[ -z "${is_custom_toolchain}" ]]; then
rustup_target_list=$(rustup ${pre_args[@]+"${pre_args[@]}"} target list)
fi
rustc_target_list=$(rustc ${pre_args[@]+"${pre_args[@]}"} --print target-list)
rustc_version=$(rustc ${pre_args[@]+"${pre_args[@]}"} -Vv | grep 'release: ' | sed 's/release: //')
nightly=''
if [[ "${rustc_version}" == *"nightly"* ]] || [[ "${rustc_version}" == *"dev"* ]]; then
nightly=1
rustup ${pre_args[@]+"${pre_args[@]}"} component add rust-src &>/dev/null
if [[ -z "${is_custom_toolchain}" ]]; then
rustup ${pre_args[@]+"${pre_args[@]}"} component add rust-src &>/dev/null
fi
fi

run() {
Expand Down

0 comments on commit af2683c

Please sign in to comment.