From aba94e9022afceab5973f0520cc6f5d87738105a Mon Sep 17 00:00:00 2001 From: guoweikang Date: Fri, 26 Jul 2024 15:53:19 +0800 Subject: [PATCH] aarch64:vfp: fix vfp ctx changed in kernel issue: https://github.com/Starry-OS/Starry/issues/16 -------- 1 Exception doesn't save VFP registers 2 kernel generate code shouldn't use VFP registers, need close -neon and -fp-armv8 3 taskctx need save/restore user application VFP ctx, need access VFP registers After rustc update, it would complain when 2&3 happend, on this commit :65a4f5896317115cf1edc74800f0da5d92923243, opened neon when fp_smid enable,it broken 2, so it create bug; after return user from kernel trap, usr vfp registers ctx are changed; This commit close neon when complie kernel, taskctx need access VFP registers through build.rs to fix Signed-off-by: guoweikang --- Makefile | 8 ++--- tools/axlibc/build.rs | 42 +++++++++++++++++++++++++ tools/axlibc/src/setjmp.rs | 59 ++++++++++++----------------------- tools/axlibc/src/vfp_setjmp.S | 37 ++++++++++++++++++++++ 4 files changed, 101 insertions(+), 45 deletions(-) create mode 100644 tools/axlibc/src/vfp_setjmp.S diff --git a/Makefile b/Makefile index c242cfc..46af9d9 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ PLATFORM ?= SMP ?= 1 MODE ?= release LOG ?= off -V ?=1 +V ?= LIBC_DIR = tools/axlibc # App options A ?= apps/monolithic_userboot @@ -122,11 +122,7 @@ ifeq ($(ARCH), x86_64) else ifeq ($(ARCH), riscv64) TARGET := riscv64gc-unknown-none-elf else ifeq ($(ARCH), aarch64) - ifeq ($(findstring fp_simd,$(FEATURES)),) - TARGET := aarch64-unknown-none-softfloat - else - TARGET := aarch64-unknown-none - endif + TARGET := aarch64-unknown-none-softfloat endif export AX_ARCH=$(ARCH) diff --git a/tools/axlibc/build.rs b/tools/axlibc/build.rs index 6c33c92..0ceddef 100644 --- a/tools/axlibc/build.rs +++ b/tools/axlibc/build.rs @@ -1,3 +1,7 @@ +use std::env; +use std::process::Command; +use std::path::PathBuf; + fn main() { fn gen_c_to_rust_bindings(in_file: &str, out_file: &str) { println!("cargo:rerun-if-changed={in_file}"); @@ -21,4 +25,42 @@ fn main() { } gen_c_to_rust_bindings("ctypes.h", "src/libctypes_gen.rs"); + + let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + if arch == "aarch64" { + aarch64_vfp_compile(); + } +} + +fn aarch64_vfp_compile() { + // 获取当前 crate 输出目录 + let out_dir = env::var("OUT_DIR").unwrap(); + // 指定汇编文件路径 + let asm_file = PathBuf::from("src/vfp_setjmp.S"); + let asm_out_file = PathBuf::from(&out_dir).join("vfp_setjmp.o"); + + // 编译汇编文件,增加 target-feature 选项 + let status = Command::new("clang") + .args(&[ + "-c", asm_file.to_str().unwrap(), + "-o", asm_out_file.to_str().unwrap(), + "-target", "aarch64-unknown-none", + "-mfpu=neon" + ]) + .status() + .expect("failed to execute clang"); + assert!(status.success(), "clang failed to compile assembly file"); + + // 打包对象文件为静态库 + let lib_out_file = PathBuf::from(&out_dir).join("libvfp_setjmp.a"); + let status = Command::new("ar") + .args(&["crus", lib_out_file.to_str().unwrap(), asm_out_file.to_str().unwrap()]) + .status() + .expect("failed to execute ar"); + assert!(status.success(), "ar failed to create static library"); + + // 指示 rustc 链接器链接汇编对象文件 + println!("cargo:rerun-if-changed=src/vfp_setjmp.S"); + println!("cargo:rustc-link-search={}", out_dir); + println!("cargo:rustc-link-lib=static=vfp_setjmp"); } diff --git a/tools/axlibc/src/setjmp.rs b/tools/axlibc/src/setjmp.rs index aed4441..9e2417a 100644 --- a/tools/axlibc/src/setjmp.rs +++ b/tools/axlibc/src/setjmp.rs @@ -2,29 +2,23 @@ use core::ffi::c_int; use crate::ctypes; +#[cfg(all(target_arch = "aarch64", feature = "fp_simd"))] +extern "C" { + fn vfp_setjmp(buf: *mut ctypes::__jmp_buf_tag); + fn vfp_longjmp(buf: *mut ctypes::__jmp_buf_tag, _val: c_int) -> !; +} + +#[cfg(all(target_arch = "aarch64", feature = "fp_simd"))] +#[no_mangle] +pub unsafe extern "C" fn setjmp(_buf: *mut ctypes::__jmp_buf_tag) { + vfp_setjmp(_buf); +} + /// `setjmp` implementation +#[cfg(all(not(target_arch = "aarch64"), not(feature = "fp_simd")))] #[naked] #[no_mangle] pub unsafe extern "C" fn setjmp(_buf: *mut ctypes::__jmp_buf_tag) { - #[cfg(all(target_arch = "aarch64", feature = "fp_simd"))] - core::arch::asm!( - " - stp x19, x20, [x0,#0] - stp x21, x22, [x0,#16] - stp x23, x24, [x0,#32] - stp x25, x26, [x0,#48] - stp x27, x28, [x0,#64] - stp x29, x30, [x0,#80] - mov x2, sp - str x2, [x0,#104] - stp d8, d9, [x0,#112] - stp d10, d11, [x0,#128] - stp d12, d13, [x0,#144] - stp d14, d15, [x0,#160] - mov x0, #0 - ret", - options(noreturn), - ); #[cfg(all(target_arch = "aarch64", not(feature = "fp_simd")))] core::arch::asm!( " @@ -119,30 +113,17 @@ pub unsafe extern "C" fn setjmp(_buf: *mut ctypes::__jmp_buf_tag) { core::arch::asm!("ret", options(noreturn)) } +#[cfg(all(target_arch = "aarch64", feature = "fp_simd"))] +#[no_mangle] +pub unsafe extern "C" fn longjmp(_buf: *mut ctypes::__jmp_buf_tag, _val: c_int) { + vfp_longjmp(_buf, _val); +} + /// `longjmp` implementation +#[cfg(all(not(target_arch = "aarch64"), not(feature = "fp_simd")))] #[naked] #[no_mangle] pub unsafe extern "C" fn longjmp(_buf: *mut ctypes::__jmp_buf_tag, _val: c_int) -> ! { - #[cfg(all(target_arch = "aarch64", feature = "fp_simd"))] - core::arch::asm!( - "ldp x19, x20, [x0,#0] - ldp x21, x22, [x0,#16] - ldp x23, x24, [x0,#32] - ldp x25, x26, [x0,#48] - ldp x27, x28, [x0,#64] - ldp x29, x30, [x0,#80] - ldr x2, [x0,#104] - mov sp, x2 - ldp d8 , d9, [x0,#112] - ldp d10, d11, [x0,#128] - ldp d12, d13, [x0,#144] - ldp d14, d15, [x0,#160] - - cmp w1, 0 - csinc w0, w1, wzr, ne - br x30", - options(noreturn), - ); #[cfg(all(target_arch = "aarch64", not(feature = "fp_simd")))] core::arch::asm!( "ldp x19, x20, [x0,#0] diff --git a/tools/axlibc/src/vfp_setjmp.S b/tools/axlibc/src/vfp_setjmp.S new file mode 100644 index 0000000..fe93b87 --- /dev/null +++ b/tools/axlibc/src/vfp_setjmp.S @@ -0,0 +1,37 @@ +.section .text +.global vfp_setjmp +vfp_setjmp: + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0,#104] + stp d8, d9, [x0,#112] + stp d10, d11, [x0,#128] + stp d12, d13, [x0,#144] + stp d14, d15, [x0,#160] + mov x0, #0 + ret + +.section .text +.global vfp_longjmp +vfp_longjmp: + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#104] + mov sp, x2 + ldp d8 , d9, [x0,#112] + ldp d10, d11, [x0,#128] + ldp d12, d13, [x0,#144] + ldp d14, d15, [x0,#160] + + cmp w1, 0 + csinc w0, w1, wzr, ne + br x30