Change:
Hi, I want to use in Rust (via inline assembly) . AMX support is by default disabled in Linux Kernel due to significant amount of memory(~10KB) that has to be save on stack when there is context switching for programs using AMX. To enable AMX we need processor with this capability (sapphirerapids), recent enough Linux kernel (5.16+) and stacks of FPU&sigalt to be of a size enough to be able to store AMX tiles (registers). Article on enabling AMX is . I have implemented a programs to enable and test AMX: one in C++ and the other in Rust. The one in C++ does initialize AMX properly, but the Rust program is not able to initialize AMX properly (likely due to stack sizes being not big enough, see "PROGRAM EXITS HERE in Rust example"). Similar problem was for python programming language. Please advice how to have AMX support enabled in Rust on SapphireRapids under Linux. building: toolchains used: 1.67.0 , 1.69.0-nightly Linux kernel: 5.19.0- OS: Centos 8.5
If the problem is stack size, set the environment variable to the size in bytes that you want for the main thread's stack. You could also spawn a new thread and set the stack size you want with
is documented as not setting the main thread's stack size, is that true? In that case this recommendation is incorrect? This doesn't mean the problem isn't stack size: it's quite plausible the issue is that Rust is consuming an abnormally large amount of the stack and a missed optimization is happening here. I believe you may programmatically increase the stack size via to something more than the 8 megabytes that Linux and gcc will default to. You may also need to use on the function, if I am reading this correctly: Also, while it shouldn't matter here, if you want upgrades to more recent kernels and userlands which have better support in general for AMX, you may want to switch from CentOS 8 to CentOS Stream 8 via and then upgrade to CentOS Stream 9. Most notably, CentOS Stream 9 should have support for Intel AMX.
Yup, I'm wrong. I must have been misremembering the code I used last time I was experimenting with a stack size issue.
Also if you want further help with debugging this, it might help if you describe the message you got from running this code, exactly. You say it exits but... what happens, exactly?
I must apologize , as I labelled wrong line with "PROGRAM EXITS HERE". So I updated the code(snippet bellow) to print error message:
ENOSPC looks to be relevant here: It looks like sigaltstack(2) was called somewhere with a small size that is not enough for the AMX states. Then, I found this -- Rust’s runtime seems to install a SIGSEGV handler via sigaltstack with SIGSTKSZ – 8KB. At least, this constant should be replaced by some dynamic value like getauxval(AT_MINSIGSTKSZ)
Ahh, okay, so it's definitely the part here, and that will be harder to fix given our own signal handlers are right there, yes. Yes, if this diagnosis is correct, we should probably make something like that change. We will want to also be prepared for... "zaniness" like Arm SVE or RV64V_Zvl1024b.
It seems that solution suggessted by works Here is a snippet that makes AMX working for Rust:
, , Here is full dummy example of using AMX from Rust (as of stable 1.67.0 toolchain) :
It is best to make the relevant auxval constant available in libc in the likely event that other Unix-y platforms introduce a matching constant, with either the same or a different value, as they sometimes do for these things, when they cannot think of a better interface than the glibc one, so I have opened
Alternatively, recent glibc versions (=2.34) may work for you as they have non-constant (MIN)SIGSTKSZ: I was told that it will eventually reference ATMINSIGSTKSZ. At the moment, it calculates the size based on CPUID, IIRC.
That probably won't work for us. Rust interacts with C by knowing how to handle the platform's C ABI, so it can call functions, but it is totally blind to macros: rustc does not have the C preprocessor. That's why we redefine these constants in things like our libc crate.
I have opened: which will resolve the sigaltstack concerns for Rust programs which correctly handles sigalstack in rustc for the implied question re: MINSIGSTKSZ and our libc bindings

Discussion:
#[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::{mmap64, munmap}; use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL}; <del> use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; </del> <ins> use libc::{sigaltstack, SS_DISABLE}; </ins> use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV}; use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};

drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed)); } <del> unsafe fn get_stackp() -> *mut libc::c_void { </del> <ins> unsafe fn get_stack() -> libc::stack_t { </ins> // OpenBSD requires this flag for stack mapping // otherwise the said mapping will fail as a no-op on most systems // and has a different meaning on FreeBSD

target_os = "dragonfly", )))] let flags = MAP_PRIVATE | MAP_ANON; <del> let stackp = mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0); </del> <ins> let sigstack_size = sigstack_size(); let page_size = page_size(); let stackp = mmap64( ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0, ); </ins> if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); } <del> let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE); </del> <ins> let guard_result = libc::mprotect(stackp, page_size, PROT_NONE); </ins> if guard_result != 0 { panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); } <del> stackp.add(page_size()) } </del> <ins> let stackp = stackp.add(page_size); </ins> <del> unsafe fn get_stack() -> libc::stack_t { libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ } </del> <ins> libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } </ins> } pub unsafe fn make_handler() -> Handler {

pub unsafe fn drop_handler(data: *mut libc::c_void) { if !data.is_null() { <ins> let sigstack_size = sigstack_size(); let page_size = page_size(); </ins> let stack = libc::stack_t { ss_sp: ptr::null_mut(), ss_flags: SS_DISABLE,

// UNIX2003 which returns ENOMEM when disabling a stack while // passing ss_size smaller than MINSIGSTKSZ. According to POSIX // both ss_sp and ss_size should be ignored in this case. <del> ss_size: SIGSTKSZ, </del> <ins> ss_size: sigstack_size, </ins> }; sigaltstack(&stack, ptr::null_mut()); // We know from `get_stackp` that the alternate stack we installed is part of a mapping // that started one page earlier, so walk back a page and unmap from there. <del> munmap(data.sub(page_size()), SIGSTKSZ + page_size()); </del> <ins> munmap(data.sub(page_size), sigstack_size + page_size); </ins> } } <ins> /// Modern kernels on modern hardware can have dynamic signal stack sizes. #[cfg(any(target_os = "linux", target_os = "android"))] fn sigstack_size() -> usize { // FIXME: reuse const from libc when available? const AT_MINSIGSTKSZ: crate::ffi::c_ulong = 51; let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) }; // If getauxval couldn't find the entry, it returns 0, // so take the higher of the "constant" and auxval. // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ libc::SIGSTKSZ.max(dynamic_sigstksz as _) } /// Not all OS support hardware where this is needed. #[cfg(not(any(target_os = "linux", target_os = "android")))] fn sigstack_size() -> usize { libc::SIGSTKSZ } </ins> } #[cfg(not(any(