109 if (
UNLIKELY(nInterruptNumber >= 256))
112 if (
UNLIKELY(pHandler != 0 && current != 0))
114 if (
UNLIKELY(pHandler == 0 && current == 0))
119 return __atomic_compare_exchange_n(&
m_pHandler[nInterruptNumber], ¤t, pHandler,
false,
120 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
131 if (
UNLIKELY(nInterruptNumber >= 256))
134 if (
UNLIKELY(pHandler != 0 && current != 0))
136 if (
UNLIKELY(pHandler == 0 && current == 0))
139 return __atomic_compare_exchange_n(&
m_pDbgHandler[nInterruptNumber], ¤t, pHandler,
false,
140 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
152#if PEDIGREE_X64_USER_ENTRY_DIAGNOSTICS
153 if (interruptState.getInterruptNumber() == 2) {
154 uintptr_t information;
156 asm volatile(
"movq %%gs:16, %0; movq %%gs:24, %1"
157 :
"=r"(information),
"=r"(index)
161 asm volatile(
"rdmsr" :
"=a"(low),
"=d"(high) :
"c"(0xc0000101));
163 auto& record = pedigree_nmi_entry_diagnostics[index];
164 record.rip = interruptState.m_Rip;
165 record.cs = interruptState.m_Cs;
166 record.rsp = interruptState.m_Rsp;
167 record.information = information;
168 record.index = index;
169 record.activeGs = (
static_cast<uint64_t
>(high) << 32) | low;
170 record.frame =
reinterpret_cast<uintptr_t
>(&interruptState);
171 __atomic_store_n(&record.count, record.count + 1, __ATOMIC_RELEASE);
177 size_t nIntNumber = interruptState.getInterruptNumber();
178 Metrics::increment(nIntNumber < 32 ? Metrics::Counter::Exception : Metrics::Counter::Interrupt);
189 pHandler->
interrupt(nIntNumber, interruptState);
198 if (
LIKELY(pHandler != 0)) {
199 pHandler->
interrupt(nIntNumber, interruptState);
210 Subsystem* pSubsystem = pProcess->getSubsystem();
211 if (pSubsystem && !interruptState.kernelMode()) {
212 size_t exceptionType =
static_cast<size_t>(Subsystem::Other);
214 exceptionType =
static_cast<size_t>(Subsystem::DivideByZero);
215 }
else if (
UNLIKELY(nIntNumber == 6)) {
216 exceptionType =
static_cast<size_t>(Subsystem::InvalidOpcode);
217 }
else if (
UNLIKELY(nIntNumber == 13)) {
218 exceptionType =
static_cast<size_t>(Subsystem::GeneralProtectionFault);
219 }
else if (
UNLIKELY(nIntNumber == 16)) {
220 exceptionType =
static_cast<size_t>(Subsystem::FpuError);
221 }
else if (
UNLIKELY(nIntNumber == 19)) {
222 exceptionType =
static_cast<size_t>(Subsystem::SpecialFpuError);
225 if (exceptionType !=
static_cast<size_t>(Subsystem::Other)) {
236 if (
LIKELY(nIntNumber < 32 && nIntNumber != 1 && nIntNumber != 3)) {
243 e.append(
"Exception #0x");
244 e.append(nIntNumber, 16);
246 e.append(g_ExceptionNames[nIntNumber]);
252 e.append(interruptState.getInstructionPointer(), 16, 16,
'0');
253 e.append(
", error code 0x");
254 e.append(interruptState.getErrorCode(), 16, 8,
'0');
265 e.append(pParent->
getId());
268 e.append(pThread->
getId());
272 if (nIntNumber == 14) {
274 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
276 e.append(cr2, 16, 16,
'0');
277 e.append(
", errorcode 0x");
278 e.append(interruptState.m_Errorcode, 16, 8,
'0');
281 if (nIntNumber == 13) {
283 if (interruptState.m_Errorcode) {
284 e.append(
" errorcode 0x");
285 e.append(interruptState.m_Errorcode, 16, 8,
'0');
288 e.append(interruptState.getInstructionPointer(), 16, 16,
'0');
291 if (nIntNumber == 8) {
293 ERROR_NOLOCK(
"(double fault, system is very unhappy)");
296 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
297 NOTICE_NOLOCK(
" -> #DF possibly caused by #PF at " <<
Hex << cr2 <<
".");
301 ERROR(
static_cast<const char*
>(e));
312 const size_t vector = interruptState.getInterruptNumber();
313#if PEDIGREE_X64_USER_ENTRY_DIAGNOSTICS
322 if (interruptState.kernelMode()) {
331 if (vector == 2 || vector == 8 || vector == 18) {
342 const uint64_t tailStart = diagnosticSample ? ActivityDiagnostics::timestamp() : 0;
348 bool terminal =
false;
355 const uint64_t affinityStart = diagnosticSample ? ActivityDiagnostics::timestamp() : 0;
357 if (diagnosticSample) {
358 ActivityDiagnostics::recordUserReturnStage(
359 ActivityDiagnostics::UserReturnStage::InterruptAffinity,
360 ActivityDiagnostics::timestamp() - affinityStart);
362 ActivityDiagnostics::recordUserReturnAffinityWait(
false);
364 if (terminal || !waited)
369 const uint64_t accountingStart = diagnosticSample ? ActivityDiagnostics::timestamp() : 0;
371 if (diagnosticSample) {
372 ActivityDiagnostics::recordUserReturnStage(
373 ActivityDiagnostics::UserReturnStage::InterruptAccounting,
374 ActivityDiagnostics::timestamp() - accountingStart);
375 ActivityDiagnostics::recordUserReturnStage(ActivityDiagnostics::UserReturnStage::InterruptTail,
376 ActivityDiagnostics::timestamp() - tailStart);
381 FATAL_NOLOCK(
"Terminal user-return commit unexpectedly returned");