diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81e0ca3..34d3d00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,12 +51,13 @@ jobs: i686-unknown-linux-gnu, aarch64-unknown-linux-gnu, riscv64gc-unknown-linux-gnu, + loongarch64-unknown-linux-gnu, ] steps: - name: checkout uses: actions/checkout@v4 - name: Set up cross - run: cargo install cross + run: cargo install cross --git https://github.com/cross-rs/cross - name: Build all features run: cross build --verbose --all-features --target ${{ matrix.target }} - name: Run tests diff --git a/Cargo.lock b/Cargo.lock index 46694dc..e0471c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "clear-cache" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20d9da0bc09582e0aa48f88476160bfe0f5f82cf97fc47eef1f701b7f59e27d2" +dependencies = [ + "libc", + "windows", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -125,6 +135,7 @@ dependencies = [ name = "static-keys" version = "0.4.0" dependencies = [ + "clear-cache", "libc", "mach2", "trybuild", diff --git a/src/arch/loongarch64.rs b/src/arch/loongarch64.rs new file mode 100644 index 0000000..92527f2 --- /dev/null +++ b/src/arch/loongarch64.rs @@ -0,0 +1,74 @@ +//! loongarch64 arch-sepcific implementations + +use crate::{JumpEntry, JumpLabelType}; + +/// Length of jump instruction to be replaced +pub const ARCH_JUMP_INS_LENGTH: usize = 4; + +const LOONGARCH64_INSN_NOP: u32 = 0x03400000; +const LOONGARCH64_INSN_B: u32 = 0x50000000; +/// New instruction generated according to jump label type and jump entry +#[inline(always)] +pub fn arch_jump_entry_instruction( + jump_label_type: JumpLabelType, + jump_entry: &JumpEntry, +) -> [u8; ARCH_JUMP_INS_LENGTH] { + match jump_label_type { + // 010100 [IMM] + // opcode I26[15:0] I26[25:16] + JumpLabelType::Jmp => { + // Note that loongarch64 only supports relative address within +/-128MB. + // In current implementation, this assumption is always hold. + let relative_addr = (jump_entry.target_addr() - jump_entry.code_addr()) as u32; + // MASK 25:16 = 0b_0000_0011_1111_1111_0000_0000_0000_0000 = 0x03FF0000 + // MASK 15:0 = 0b_0000_0000_0000_0000_1111_1111_1111_1111 = 0x0000FFFF + let mut b = LOONGARCH64_INSN_B; + let relative_addr = relative_addr >> 2; + b |= ((relative_addr & 0x03FF0000) >> 16) | ((relative_addr & 0x0000FFFF) << 10); + b.to_ne_bytes() + } + JumpLabelType::Nop => LOONGARCH64_INSN_NOP.to_ne_bytes(), + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! arch_static_key_init_nop_asm_template { + () => { + ::core::concat!( + r#" + 2: + nop + .pushsection "#, + $crate::os_static_key_sec_name_attr!(), + r#" + .balign 8 + .quad 2b - . + .quad {0} - . + .quad {1} + {2} - . + .popsection + "# + ) + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! arch_static_key_init_jmp_asm_template { + () => { + ::core::concat!( + r#" + 2: + b {0} + .pushsection "#, + $crate::os_static_key_sec_name_attr!(), + r#" + .balign 8 + .quad 2b - . + .quad {0} - . + .quad {1} + {2} - . + .popsection + "# + ) + }; +} diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 03ea04a..cce03c3 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -17,6 +17,10 @@ pub use aarch64::*; #[cfg(target_arch = "riscv64")] mod riscv64; - #[cfg(target_arch = "riscv64")] pub use riscv64::*; + +#[cfg(target_arch = "loongarch64")] +mod loongarch64; +#[cfg(target_arch = "loongarch64")] +pub use loongarch64::*;