108 if (
UNLIKELY(nInterruptNumber >= 256))
111 if (
UNLIKELY(pHandler != 0 && current != 0))
113 if (
UNLIKELY(pHandler == 0 && current == 0))
118 return __atomic_compare_exchange_n(&
m_pHandler[nInterruptNumber], ¤t, pHandler,
false,
119 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
130 if (
UNLIKELY(nInterruptNumber >= 256))
133 if (
UNLIKELY(pHandler != 0 && current != 0))
135 if (
UNLIKELY(pHandler == 0 && current == 0))
138 return __atomic_compare_exchange_n(&
m_pDbgHandler[nInterruptNumber], ¤t, pHandler,
false,
139 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
151#if PEDIGREE_X64_USER_ENTRY_DIAGNOSTICS
152 if (interruptState.getInterruptNumber() == 2) {
153 uintptr_t information;
155 asm volatile(
"movq %%gs:16, %0; movq %%gs:24, %1"
156 :
"=r"(information),
"=r"(index)
160 asm volatile(
"rdmsr" :
"=a"(low),
"=d"(high) :
"c"(0xc0000101));
162 auto& record = pedigree_nmi_entry_diagnostics[index];
163 record.rip = interruptState.m_Rip;
164 record.cs = interruptState.m_Cs;
165 record.rsp = interruptState.m_Rsp;
166 record.information = information;
167 record.index = index;
168 record.activeGs = (
static_cast<uint64_t
>(high) << 32) | low;
169 record.frame =
reinterpret_cast<uintptr_t
>(&interruptState);
170 __atomic_store_n(&record.count, record.count + 1, __ATOMIC_RELEASE);
176 size_t nIntNumber = interruptState.getInterruptNumber();
177 Metrics::increment(nIntNumber < 32 ? Metrics::Counter::Exception : Metrics::Counter::Interrupt);
188 pHandler->
interrupt(nIntNumber, interruptState);
197 if (
LIKELY(pHandler != 0)) {
198 pHandler->
interrupt(nIntNumber, interruptState);
209 Subsystem* pSubsystem = pProcess->getSubsystem();
210 if (pSubsystem && !interruptState.kernelMode()) {
211 size_t exceptionType =
static_cast<size_t>(Subsystem::Other);
213 exceptionType =
static_cast<size_t>(Subsystem::DivideByZero);
214 }
else if (
UNLIKELY(nIntNumber == 6)) {
215 exceptionType =
static_cast<size_t>(Subsystem::InvalidOpcode);
216 }
else if (
UNLIKELY(nIntNumber == 13)) {
217 exceptionType =
static_cast<size_t>(Subsystem::GeneralProtectionFault);
218 }
else if (
UNLIKELY(nIntNumber == 16)) {
219 exceptionType =
static_cast<size_t>(Subsystem::FpuError);
220 }
else if (
UNLIKELY(nIntNumber == 19)) {
221 exceptionType =
static_cast<size_t>(Subsystem::SpecialFpuError);
224 if (exceptionType !=
static_cast<size_t>(Subsystem::Other)) {
235 if (
LIKELY(nIntNumber < 32 && nIntNumber != 1 && nIntNumber != 3)) {
243 e.append(
"Exception #0x");
244 e.append(nIntNumber, 16);
246 e.append(g_ExceptionNames[nIntNumber]);
256 e.append(pParent->
getId());
259 e.append(pThread->
getId());
263 if (nIntNumber == 14) {
265 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
267 e.append(cr2, 16, 16,
'0');
268 e.append(
", errorcode 0x");
269 e.append(interruptState.m_Errorcode, 16, 8,
'0');
272 if (nIntNumber == 13) {
274 if (interruptState.m_Errorcode) {
275 e.append(
" errorcode 0x");
276 e.append(interruptState.m_Errorcode, 16, 8,
'0');
279 e.append(interruptState.getInstructionPointer(), 16, 16,
'0');
282 if (nIntNumber == 8) {
284 ERROR_NOLOCK(
"(double fault, system is very unhappy)");
287 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
288 NOTICE_NOLOCK(
" -> #DF possibly caused by #PF at " <<
Hex << cr2 <<
".");
292 ERROR(
static_cast<const char*
>(e));
303 const size_t vector = interruptState.getInterruptNumber();
304#if PEDIGREE_X64_USER_ENTRY_DIAGNOSTICS
313 if (interruptState.kernelMode()) {
322 if (vector == 2 || vector == 8 || vector == 18) {
333 const uint64_t tailStart = diagnosticSample ? ActivityDiagnostics::timestamp() : 0;
339 bool terminal =
false;
346 const uint64_t affinityStart = diagnosticSample ? ActivityDiagnostics::timestamp() : 0;
348 if (diagnosticSample) {
349 ActivityDiagnostics::recordUserReturnStage(
350 ActivityDiagnostics::UserReturnStage::InterruptAffinity,
351 ActivityDiagnostics::timestamp() - affinityStart);
353 ActivityDiagnostics::recordUserReturnAffinityWait(
false);
355 if (terminal || !waited)
360 const uint64_t accountingStart = diagnosticSample ? ActivityDiagnostics::timestamp() : 0;
362 if (diagnosticSample) {
363 ActivityDiagnostics::recordUserReturnStage(
364 ActivityDiagnostics::UserReturnStage::InterruptAccounting,
365 ActivityDiagnostics::timestamp() - accountingStart);
366 ActivityDiagnostics::recordUserReturnStage(ActivityDiagnostics::UserReturnStage::InterruptTail,
367 ActivityDiagnostics::timestamp() - tailStart);
372 FATAL_NOLOCK(
"Terminal user-return commit unexpectedly returned");