x86: prevent unconditional writes to DebugCtl MSR
Otherwise, enabling (or better, subsequent disabling) of single stepping would cause a kernel oops on CPUs not having this MSR. The patch could have been added a conditional to the MSR write in user_disable_single_step(), but centralizing the updates seems safer and (looking forward) better manageable. Signed-off-by: Jan Beulich <jbeulich@novell.com> Cc: Markus Metzger <markus.t.metzger@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Родитель
f694010185
Коммит
5b0e508415
|
@ -410,13 +410,13 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
|
||||||
static void __kprobes clear_btf(void)
|
static void __kprobes clear_btf(void)
|
||||||
{
|
{
|
||||||
if (test_thread_flag(TIF_DEBUGCTLMSR))
|
if (test_thread_flag(TIF_DEBUGCTLMSR))
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
|
update_debugctlmsr(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __kprobes restore_btf(void)
|
static void __kprobes restore_btf(void)
|
||||||
{
|
{
|
||||||
if (test_thread_flag(TIF_DEBUGCTLMSR))
|
if (test_thread_flag(TIF_DEBUGCTLMSR))
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr);
|
update_debugctlmsr(current->thread.debugctlmsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
||||||
|
|
|
@ -564,12 +564,12 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
||||||
/* we clear debugctl to make sure DS
|
/* we clear debugctl to make sure DS
|
||||||
* is not in use when we change it */
|
* is not in use when we change it */
|
||||||
debugctl = 0;
|
debugctl = 0;
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
|
update_debugctlmsr(0);
|
||||||
wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
|
wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next->debugctlmsr != debugctl)
|
if (next->debugctlmsr != debugctl)
|
||||||
wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
|
update_debugctlmsr(next->debugctlmsr);
|
||||||
|
|
||||||
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
||||||
set_debugreg(next->debugreg0, 0);
|
set_debugreg(next->debugreg0, 0);
|
||||||
|
|
|
@ -563,12 +563,12 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
|
||||||
/* we clear debugctl to make sure DS
|
/* we clear debugctl to make sure DS
|
||||||
* is not in use when we change it */
|
* is not in use when we change it */
|
||||||
debugctl = 0;
|
debugctl = 0;
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
|
update_debugctlmsr(0);
|
||||||
wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
|
wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next->debugctlmsr != debugctl)
|
if (next->debugctlmsr != debugctl)
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
|
update_debugctlmsr(next->debugctlmsr);
|
||||||
|
|
||||||
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
||||||
loaddebug(next, 0);
|
loaddebug(next, 0);
|
||||||
|
|
|
@ -148,7 +148,7 @@ static void write_debugctlmsr(struct task_struct *child, unsigned long val)
|
||||||
if (child != current)
|
if (child != current)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
|
update_debugctlmsr(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -741,6 +741,15 @@ extern void switch_to_new_gdt(void);
|
||||||
extern void cpu_init(void);
|
extern void cpu_init(void);
|
||||||
extern void init_gdt(int cpu);
|
extern void init_gdt(int cpu);
|
||||||
|
|
||||||
|
static inline void update_debugctlmsr(unsigned long debugctlmsr)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_X86_DEBUGCTLMSR
|
||||||
|
if (boot_cpu_data.x86 < 6)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* from system description table in BIOS. Mostly for MCA use, but
|
* from system description table in BIOS. Mostly for MCA use, but
|
||||||
* others may find it useful:
|
* others may find it useful:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче