Fix page fault handling on linux

Change-Id: Ic7c2697d9e143c9e4d668974fce0ade3fe060a46
Signed-off-by: Jobczyk, Lukasz <lukasz.jobczyk@intel.com>
This commit is contained in:
Jobczyk, Lukasz
2019-11-26 09:25:32 +01:00
committed by sys_ocldev
parent 9727de58b0
commit 00243a455d
3 changed files with 94 additions and 7 deletions

View File

@@ -21,7 +21,7 @@ std::function<void(int signal, siginfo_t *info, void *context)> PageFaultManager
PageFaultManagerLinux::PageFaultManagerLinux() {
pageFaultHandler = [&](int signal, siginfo_t *info, void *context) {
if (!this->verifyPageFault(info->si_addr)) {
previousHandler.sa_sigaction(signal, info, context);
callPreviousHandler(signal, info, context);
}
};
@@ -33,8 +33,10 @@ PageFaultManagerLinux::PageFaultManagerLinux() {
}
PageFaultManagerLinux::~PageFaultManagerLinux() {
auto retVal = sigaction(SIGSEGV, &previousHandler, nullptr);
UNRECOVERABLE_IF(retVal != 0);
if (!previousHandlerRestored) {
auto retVal = sigaction(SIGSEGV, &previousHandler, nullptr);
UNRECOVERABLE_IF(retVal != 0);
}
}
void PageFaultManagerLinux::pageFaultHandlerWrapper(int signal, siginfo_t *info, void *context) {
@@ -50,4 +52,20 @@ void PageFaultManagerLinux::protectCPUMemoryAccess(void *ptr, size_t size) {
auto retVal = mprotect(ptr, size, PROT_NONE);
UNRECOVERABLE_IF(retVal != 0);
}
void PageFaultManagerLinux::callPreviousHandler(int signal, siginfo_t *info, void *context) {
if (previousHandler.sa_flags & SA_SIGINFO) {
previousHandler.sa_sigaction(signal, info, context);
} else {
if (previousHandler.sa_handler == SIG_DFL) {
auto retVal = sigaction(SIGSEGV, &previousHandler, nullptr);
UNRECOVERABLE_IF(retVal != 0);
previousHandlerRestored = true;
} else if (previousHandler.sa_handler == SIG_IGN) {
return;
} else {
previousHandler.sa_handler(signal);
}
}
}
} // namespace NEO

View File

@@ -24,6 +24,9 @@ class PageFaultManagerLinux : public PageFaultManager {
void allowCPUMemoryAccess(void *ptr, size_t size) override;
void protectCPUMemoryAccess(void *ptr, size_t size) override;
void callPreviousHandler(int signal, siginfo_t *info, void *context);
bool previousHandlerRestored = false;
static std::function<void(int signal, siginfo_t *info, void *context)> pageFaultHandler;
struct sigaction previousHandler = {};
};