x86: x86-32 thread_struct.debugreg
This replaces the debugreg[7] member of thread_struct with individual members debugreg0, etc. This saves two words for the dummies 4 and 5, and harmonizes the code between 32 and 64. Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
committed by
Ingo Molnar
parent
d277fb89df
commit
0f5340933f
@@ -445,7 +445,12 @@ void flush_thread(void)
|
|||||||
{
|
{
|
||||||
struct task_struct *tsk = current;
|
struct task_struct *tsk = current;
|
||||||
|
|
||||||
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
|
tsk->thread.debugreg0 = 0;
|
||||||
|
tsk->thread.debugreg1 = 0;
|
||||||
|
tsk->thread.debugreg2 = 0;
|
||||||
|
tsk->thread.debugreg3 = 0;
|
||||||
|
tsk->thread.debugreg6 = 0;
|
||||||
|
tsk->thread.debugreg7 = 0;
|
||||||
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
|
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
|
||||||
clear_tsk_thread_flag(tsk, TIF_DEBUG);
|
clear_tsk_thread_flag(tsk, TIF_DEBUG);
|
||||||
/*
|
/*
|
||||||
@@ -522,7 +527,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
|
|||||||
*/
|
*/
|
||||||
void dump_thread(struct pt_regs * regs, struct user * dump)
|
void dump_thread(struct pt_regs * regs, struct user * dump)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
u16 gs;
|
u16 gs;
|
||||||
|
|
||||||
/* changed the size calculations - should hopefully work better. lbt */
|
/* changed the size calculations - should hopefully work better. lbt */
|
||||||
@@ -533,8 +537,14 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
|
|||||||
dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
||||||
dump->u_dsize -= dump->u_tsize;
|
dump->u_dsize -= dump->u_tsize;
|
||||||
dump->u_ssize = 0;
|
dump->u_ssize = 0;
|
||||||
for (i = 0; i < 8; i++)
|
dump->u_debugreg[0] = current->thread.debugreg0;
|
||||||
dump->u_debugreg[i] = current->thread.debugreg[i];
|
dump->u_debugreg[1] = current->thread.debugreg1;
|
||||||
|
dump->u_debugreg[2] = current->thread.debugreg2;
|
||||||
|
dump->u_debugreg[3] = current->thread.debugreg3;
|
||||||
|
dump->u_debugreg[4] = 0;
|
||||||
|
dump->u_debugreg[5] = 0;
|
||||||
|
dump->u_debugreg[6] = current->thread.debugreg6;
|
||||||
|
dump->u_debugreg[7] = current->thread.debugreg7;
|
||||||
|
|
||||||
if (dump->start_stack < TASK_SIZE)
|
if (dump->start_stack < TASK_SIZE)
|
||||||
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
|
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
|
||||||
@@ -612,13 +622,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
|||||||
wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
|
wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
|
||||||
|
|
||||||
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
||||||
set_debugreg(next->debugreg[0], 0);
|
set_debugreg(next->debugreg0, 0);
|
||||||
set_debugreg(next->debugreg[1], 1);
|
set_debugreg(next->debugreg1, 1);
|
||||||
set_debugreg(next->debugreg[2], 2);
|
set_debugreg(next->debugreg2, 2);
|
||||||
set_debugreg(next->debugreg[3], 3);
|
set_debugreg(next->debugreg3, 3);
|
||||||
/* no 4 and 5 */
|
/* no 4 and 5 */
|
||||||
set_debugreg(next->debugreg[6], 6);
|
set_debugreg(next->debugreg6, 6);
|
||||||
set_debugreg(next->debugreg[7], 7);
|
set_debugreg(next->debugreg7, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SECCOMP
|
#ifdef CONFIG_SECCOMP
|
||||||
@@ -869,4 +879,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
|
|||||||
unsigned long range_end = mm->brk + 0x02000000;
|
unsigned long range_end = mm->brk + 0x02000000;
|
||||||
return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
|
return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -133,19 +133,39 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
|
|||||||
*/
|
*/
|
||||||
static unsigned long ptrace_get_debugreg(struct task_struct *child, int n)
|
static unsigned long ptrace_get_debugreg(struct task_struct *child, int n)
|
||||||
{
|
{
|
||||||
return child->thread.debugreg[n];
|
switch (n) {
|
||||||
|
case 0: return child->thread.debugreg0;
|
||||||
|
case 1: return child->thread.debugreg1;
|
||||||
|
case 2: return child->thread.debugreg2;
|
||||||
|
case 3: return child->thread.debugreg3;
|
||||||
|
case 6: return child->thread.debugreg6;
|
||||||
|
case 7: return child->thread.debugreg7;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ptrace_set_debugreg(struct task_struct *child,
|
static int ptrace_set_debugreg(struct task_struct *child,
|
||||||
int n, unsigned long data)
|
int n, unsigned long data)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (unlikely(n == 4 || n == 5))
|
if (unlikely(n == 4 || n == 5))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (n < 4 && unlikely(data >= TASK_SIZE - 3))
|
if (n < 4 && unlikely(data >= TASK_SIZE - 3))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (n == 7) {
|
switch (n) {
|
||||||
|
case 0: child->thread.debugreg0 = data; break;
|
||||||
|
case 1: child->thread.debugreg1 = data; break;
|
||||||
|
case 2: child->thread.debugreg2 = data; break;
|
||||||
|
case 3: child->thread.debugreg3 = data; break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
child->thread.debugreg6 = data;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
/*
|
/*
|
||||||
* Sanity-check data. Take one half-byte at once with
|
* Sanity-check data. Take one half-byte at once with
|
||||||
* check = (val >> (16 + 4*i)) & 0xf. It contains the
|
* check = (val >> (16 + 4*i)) & 0xf. It contains the
|
||||||
@@ -176,19 +196,18 @@ static int ptrace_set_debugreg(struct task_struct *child,
|
|||||||
* 64-bit kernel), so the x86_64 mask value is 0x5454.
|
* 64-bit kernel), so the x86_64 mask value is 0x5454.
|
||||||
* See the AMD manual no. 24593 (AMD64 System Programming)
|
* See the AMD manual no. 24593 (AMD64 System Programming)
|
||||||
*/
|
*/
|
||||||
int i;
|
|
||||||
data &= ~DR_CONTROL_RESERVED;
|
data &= ~DR_CONTROL_RESERVED;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
|
if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
child->thread.debugreg7 = data;
|
||||||
if (data)
|
if (data)
|
||||||
set_tsk_thread_flag(child, TIF_DEBUG);
|
set_tsk_thread_flag(child, TIF_DEBUG);
|
||||||
else
|
else
|
||||||
clear_tsk_thread_flag(child, TIF_DEBUG);
|
clear_tsk_thread_flag(child, TIF_DEBUG);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
child->thread.debugreg[n] = data;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -605,8 +605,8 @@ static void fastcall do_signal(struct pt_regs *regs)
|
|||||||
* have been cleared if the watchpoint triggered
|
* have been cleared if the watchpoint triggered
|
||||||
* inside the kernel.
|
* inside the kernel.
|
||||||
*/
|
*/
|
||||||
if (unlikely(current->thread.debugreg[7]))
|
if (unlikely(current->thread.debugreg7))
|
||||||
set_debugreg(current->thread.debugreg[7], 7);
|
set_debugreg(current->thread.debugreg7, 7);
|
||||||
|
|
||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
|
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
|
||||||
|
@@ -852,7 +852,7 @@ fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code)
|
|||||||
|
|
||||||
/* Mask out spurious debug traps due to lazy DR7 setting */
|
/* Mask out spurious debug traps due to lazy DR7 setting */
|
||||||
if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
|
if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
|
||||||
if (!tsk->thread.debugreg[7])
|
if (!tsk->thread.debugreg7)
|
||||||
goto clear_dr7;
|
goto clear_dr7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,7 +860,7 @@ fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code)
|
|||||||
goto debug_vm86;
|
goto debug_vm86;
|
||||||
|
|
||||||
/* Save debug status register where ptrace can see it */
|
/* Save debug status register where ptrace can see it */
|
||||||
tsk->thread.debugreg[6] = condition;
|
tsk->thread.debugreg6 = condition;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Single-stepping through TF: make sure we ignore any events in
|
* Single-stepping through TF: make sure we ignore any events in
|
||||||
|
@@ -74,14 +74,14 @@ static void fix_processor_context(void)
|
|||||||
/*
|
/*
|
||||||
* Now maybe reload the debug registers
|
* Now maybe reload the debug registers
|
||||||
*/
|
*/
|
||||||
if (current->thread.debugreg[7]){
|
if (current->thread.debugreg7) {
|
||||||
set_debugreg(current->thread.debugreg[0], 0);
|
set_debugreg(current->thread.debugreg0, 0);
|
||||||
set_debugreg(current->thread.debugreg[1], 1);
|
set_debugreg(current->thread.debugreg1, 1);
|
||||||
set_debugreg(current->thread.debugreg[2], 2);
|
set_debugreg(current->thread.debugreg2, 2);
|
||||||
set_debugreg(current->thread.debugreg[3], 3);
|
set_debugreg(current->thread.debugreg3, 3);
|
||||||
/* no 4 and 5 */
|
/* no 4 and 5 */
|
||||||
set_debugreg(current->thread.debugreg[6], 6);
|
set_debugreg(current->thread.debugreg6, 6);
|
||||||
set_debugreg(current->thread.debugreg[7], 7);
|
set_debugreg(current->thread.debugreg7, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -353,7 +353,12 @@ struct thread_struct {
|
|||||||
unsigned long fs;
|
unsigned long fs;
|
||||||
unsigned long gs;
|
unsigned long gs;
|
||||||
/* Hardware debugging registers */
|
/* Hardware debugging registers */
|
||||||
unsigned long debugreg[8]; /* %%db0-7 debug registers */
|
unsigned long debugreg0;
|
||||||
|
unsigned long debugreg1;
|
||||||
|
unsigned long debugreg2;
|
||||||
|
unsigned long debugreg3;
|
||||||
|
unsigned long debugreg6;
|
||||||
|
unsigned long debugreg7;
|
||||||
/* fault info */
|
/* fault info */
|
||||||
unsigned long cr2, trap_no, error_code;
|
unsigned long cr2, trap_no, error_code;
|
||||||
/* floating point info */
|
/* floating point info */
|
||||||
|
Reference in New Issue
Block a user