x86: add x86_clear_dbregs() helper

Move the code from exec_setregs() to reset debug registers state on exec,
to the x86_clear_dbregs() helper

Reviewed by:	jhb
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D29687
This commit is contained in:
Konstantin Belousov 2021-04-10 02:19:23 +03:00
parent 86e352c934
commit a8b75a57c9
3 changed files with 59 additions and 42 deletions

View File

@ -581,6 +581,34 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
}
#endif
/*
* Reset the hardware debug registers if they were in use.
* They won't have any meaning for the newly exec'd process.
*/
void
x86_clear_dbregs(struct pcb *pcb)
{
if ((pcb->pcb_flags & PCB_DBREGS) == 0)
return;
pcb->pcb_dr0 = 0;
pcb->pcb_dr1 = 0;
pcb->pcb_dr2 = 0;
pcb->pcb_dr3 = 0;
pcb->pcb_dr6 = 0;
pcb->pcb_dr7 = 0;
if (pcb == curpcb) {
/*
* Clear the debug registers on the running CPU,
* otherwise they will end up affecting the next
* process we switch to.
*/
reset_dbregs();
}
clear_pcb_flags(pcb, PCB_DBREGS);
}
/*
* Reset registers to default values on exec.
*/
@ -617,27 +645,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
regs->tf_gs = _ugssel;
regs->tf_flags = TF_HASSEGS;
/*
* Reset the hardware debug registers if they were in use.
* They won't have any meaning for the newly exec'd process.
*/
if (pcb->pcb_flags & PCB_DBREGS) {
pcb->pcb_dr0 = 0;
pcb->pcb_dr1 = 0;
pcb->pcb_dr2 = 0;
pcb->pcb_dr3 = 0;
pcb->pcb_dr6 = 0;
pcb->pcb_dr7 = 0;
if (pcb == curpcb) {
/*
* Clear the debug registers on the running
* CPU, otherwise they will end up affecting
* the next process we switch to.
*/
reset_dbregs();
}
clear_pcb_flags(pcb, PCB_DBREGS);
}
x86_clear_dbregs(pcb);
/*
* Drop the FP state if we hold it, so that the process gets a

View File

@ -1121,6 +1121,34 @@ setup_priv_lcall_gate(struct proc *p)
}
#endif
/*
* Reset the hardware debug registers if they were in use.
* They won't have any meaning for the newly exec'd process.
*/
void
x86_clear_dbregs(struct pcb *pcb)
{
if ((pcb->pcb_flags & PCB_DBREGS) == 0)
return;
pcb->pcb_dr0 = 0;
pcb->pcb_dr1 = 0;
pcb->pcb_dr2 = 0;
pcb->pcb_dr3 = 0;
pcb->pcb_dr6 = 0;
pcb->pcb_dr7 = 0;
if (pcb == curpcb) {
/*
* Clear the debug registers on the running CPU,
* otherwise they will end up affecting the next
* process we switch to.
*/
reset_dbregs();
}
pcb->pcb_flags &= ~PCB_DBREGS;
}
/*
* Reset registers to default values on exec.
*/
@ -1174,27 +1202,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
/* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
regs->tf_ebx = (register_t)imgp->ps_strings;
/*
* Reset the hardware debug registers if they were in use.
* They won't have any meaning for the newly exec'd process.
*/
if (pcb->pcb_flags & PCB_DBREGS) {
pcb->pcb_dr0 = 0;
pcb->pcb_dr1 = 0;
pcb->pcb_dr2 = 0;
pcb->pcb_dr3 = 0;
pcb->pcb_dr6 = 0;
pcb->pcb_dr7 = 0;
if (pcb == curpcb) {
/*
* Clear the debug registers on the running
* CPU, otherwise they will end up affecting
* the next process we switch to.
*/
reset_dbregs();
}
pcb->pcb_flags &= ~PCB_DBREGS;
}
x86_clear_dbregs(pcb);
pcb->pcb_initial_npxcw = __INITIAL_NPXCW__;

View File

@ -123,6 +123,7 @@ void cpu_setregs(void);
int dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size, int access);
int dbreg_clr_watchpoint(vm_offset_t addr, vm_size_t size);
void dbreg_list_watchpoints(void);
void x86_clear_dbregs(struct pcb *pcb);
bool disable_wp(void);
void restore_wp(bool old_wp);
void finishidentcpu(void);