-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Page Fault Error Code not properly read #513
Comments
Thanks a lot for reporting! I can reproduce it. The problem seems to be in LLVM, since the generated assembly is faulty: […]
mov rax,QWORD PTR [rsp+0x70]
lea rcx,[rsp+0x70]
mov QWORD PTR [rsp+0x10],rcx
mov rdi,QWORD PTR [rsp+0x10]
mov rsi,QWORD PTR [rsp+0x70]
mov QWORD PTR [rsp+0x8],rax
call 205170 <foo> Foo is a test function that takes the stack frame and the error code as arguments in rdi and rsi registers. The rsi register is loaded with the instruction pointer field of the stack frame ( Interestingly it is correct in mov rsi,QWORD PTR [rsp+0x58]
lea rdi,[rsp+0x60]
call 203a70 <foo> I printed the error code and it looks correct too. Does it work in release mode for you too? |
You know, I did always think that sometimes the error flags looked a little off in flower... |
I took a quick look at the LLVM code, but I fear that I don't know enough of LLVM to be able to solve this. I opened rust-lang/rust#57270 for this. |
Hi, checking --release mode, the error indeed goes away as far as I can tell, though I need debug mode for other reasons atm :( |
Thanks for checking! I'm currently working on a fix that also works in debug mode. |
I am able to reproduce this issue in Release mode: #[derive(Debug, Clone, Copy)]
#[repr(packed)]
struct StackFrame {
pub ip: u64,
pub cs: u64,
pub flags: u64,
pub sp: u64,
pub ss: u64
}
extern "x86-interrupt" fn isr_0x0e(frame: &StackFrame, error_code: u64) {
panic!("Exception #PF ({:x}): {:#x?}", error_code, frame);
} Relevant assembly for isr_0x0e: // 0xc0(%rsp) is the correct address of the stack frame.
// error code is at 0xb8(%rsp)
lea 0xc0(%rsp),%rax
mov %rax,0x10(%rsp)
lea 0xc0(%rsp),%rax
mov %rax,0x18(%rsp) still outputs %rip as the error code on a PF exception even if I am compiling using "cargo xbuild --release". I am using the latest nightly build of rust. |
@Richard-W Thanks! I think I found the issue in LLVM and I'm currently preparing a patch for it. |
The issue should be fixed on current nightlies. |
We previously did not use the error code because of #513, which is now fixed.
We previously did not use the error code because of #513, which is now fixed.
We previously did not use the error code because of #513, which is now fixed.
During development I was encountering strange error codes set for the page fault handler.
After some experimenting and feedback with other developers it turns out that LLVM doesn't seem to properly handle the x86-interrupt ABI; the return address (RIP) is read instead of the actual error code, causing some rather silly bugs.
To fix this I made the following adjustments to my own code:
With this fix makes the stack_frame variable accessible; trying to read values causes a GPF for me, so it's half of a fix.
Using the original
extern "x86-interrupt" fn(&mut ExceptionStackFrame, PageFaultErrorCode)
function signature doesn't seem to work by default, ie, without adjusting the stack but I can't seem to get rust to properly clone the PFE Code without causing another GPF.However, the interrupt functions correctly despite this and calling and referencing kernel related functions and data works without issue.
From what I can gather this is an issue with either the Rust compiler or LLVM, this should possibly be mentioned on the page for CPU Exceptions.
This occurs on Rust nightly-2018-12-30 on Linux and QEMU with and without KVM.
The text was updated successfully, but these errors were encountered: