/* * Define bits that are always set to 1 in DR7, only bit 10 is * architecturally reserved to '1'. * * This is also the init/reset value for DR7.
*/ #define DR7_FIXED_1 0x00000400
DECLARE_PER_CPU(unsignedlong, cpu_dr7);
#ifndef CONFIG_PARAVIRT_XXL /* * These special macros can be used to get or set a debugging register
*/ #define get_debugreg(var, register) \
(var) = native_get_debugreg(register) #define set_debugreg(value, register) \
native_set_debugreg(register, value) #endif
switch (regno) { case 0: asm("mov %%db0, %0" :"=r" (val)); break; case 1: asm("mov %%db1, %0" :"=r" (val)); break; case 2: asm("mov %%db2, %0" :"=r" (val)); break; case 3: asm("mov %%db3, %0" :"=r" (val)); break; case 6: asm("mov %%db6, %0" :"=r" (val)); break; case 7: /* * Use "asm volatile" for DR7 reads to forbid re-ordering them * with other code. * * This is needed because a DR7 access can cause a #VC exception * when running under SEV-ES. Taking a #VC exception is not a * safe thing to do just anywhere in the entry code and * re-ordering might place the access into an unsafe location. * * This happened in the NMI handler, where the DR7 read was * re-ordered to happen before the call to sev_es_ist_enter(), * causing stack recursion.
*/ asmvolatile("mov %%db7, %0" : "=r" (val)); break; default:
BUG();
} return val;
}
static __always_inline void native_set_debugreg(int regno, unsignedlong value)
{ switch (regno) { case 0: asm("mov %0, %%db0" ::"r" (value)); break; case 1: asm("mov %0, %%db1" ::"r" (value)); break; case 2: asm("mov %0, %%db2" ::"r" (value)); break; case 3: asm("mov %0, %%db3" ::"r" (value)); break; case 6: asm("mov %0, %%db6" ::"r" (value)); break; case 7: /* * Use "asm volatile" for DR7 writes to forbid re-ordering them * with other code. * * While is didn't happen with a DR7 write (see the DR7 read * comment above which explains where it happened), add the * "asm volatile" here too to avoid similar problems in the * future.
*/ asmvolatile("mov %0, %%db7" ::"r" (value)); break; default:
BUG();
}
}
staticinlinevoid hw_breakpoint_disable(void)
{ /* Reset the control register for HW Breakpoint */
set_debugreg(DR7_FIXED_1, 7);
if (static_cpu_has(X86_FEATURE_HYPERVISOR) && !hw_breakpoint_active()) return 0;
get_debugreg(dr7, 7);
/* Architecturally set bit */
dr7 &= ~DR7_FIXED_1; if (dr7)
set_debugreg(DR7_FIXED_1, 7);
/* * Ensure the compiler doesn't lower the above statements into * the critical section; disabling breakpoints late would not * be good.
*/
barrier();
return dr7;
}
static __always_inline void local_db_restore(unsignedlong dr7)
{ /* * Ensure the compiler doesn't raise this statement into * the critical section; enabling breakpoints early would * not be good.
*/
barrier(); if (dr7)
set_debugreg(dr7, 7);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.