xref: /openbmc/linux/arch/x86/kernel/step.c (revision e1f287735c1e58c653b516931b5d3dd899edcb77)
1fa1e03eaSRoland McGrath /*
2fa1e03eaSRoland McGrath  * x86 single-step support code, common to 32-bit and 64-bit.
3fa1e03eaSRoland McGrath  */
4fa1e03eaSRoland McGrath #include <linux/sched.h>
5fa1e03eaSRoland McGrath #include <linux/mm.h>
6fa1e03eaSRoland McGrath #include <linux/ptrace.h>
7fa1e03eaSRoland McGrath 
87122ec81SRoland McGrath #ifdef CONFIG_X86_32
97122ec81SRoland McGrath static
107122ec81SRoland McGrath #endif
11fa1e03eaSRoland McGrath unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *regs)
12fa1e03eaSRoland McGrath {
13fa1e03eaSRoland McGrath 	unsigned long addr, seg;
14fa1e03eaSRoland McGrath 
157122ec81SRoland McGrath #ifdef CONFIG_X86_64
16fa1e03eaSRoland McGrath 	addr = regs->rip;
17fa1e03eaSRoland McGrath 	seg = regs->cs & 0xffff;
187122ec81SRoland McGrath #else
197122ec81SRoland McGrath 	addr = regs->eip;
207122ec81SRoland McGrath 	seg = regs->xcs & 0xffff;
217122ec81SRoland McGrath 	if (regs->eflags & X86_EFLAGS_VM) {
227122ec81SRoland McGrath 		addr = (addr & 0xffff) + (seg << 4);
237122ec81SRoland McGrath 		return addr;
247122ec81SRoland McGrath 	}
257122ec81SRoland McGrath #endif
26fa1e03eaSRoland McGrath 
27fa1e03eaSRoland McGrath 	/*
28fa1e03eaSRoland McGrath 	 * We'll assume that the code segments in the GDT
29fa1e03eaSRoland McGrath 	 * are all zero-based. That is largely true: the
30fa1e03eaSRoland McGrath 	 * TLS segments are used for data, and the PNPBIOS
31fa1e03eaSRoland McGrath 	 * and APM bios ones we just ignore here.
32fa1e03eaSRoland McGrath 	 */
333f80c1adSRoland McGrath 	if ((seg & SEGMENT_TI_MASK) == SEGMENT_LDT) {
34fa1e03eaSRoland McGrath 		u32 *desc;
35fa1e03eaSRoland McGrath 		unsigned long base;
36fa1e03eaSRoland McGrath 
37fa1e03eaSRoland McGrath 		seg &= ~7UL;
38fa1e03eaSRoland McGrath 
39fa1e03eaSRoland McGrath 		mutex_lock(&child->mm->context.lock);
40fa1e03eaSRoland McGrath 		if (unlikely((seg >> 3) >= child->mm->context.size))
41fa1e03eaSRoland McGrath 			addr = -1L; /* bogus selector, access would fault */
42fa1e03eaSRoland McGrath 		else {
43fa1e03eaSRoland McGrath 			desc = child->mm->context.ldt + seg;
44fa1e03eaSRoland McGrath 			base = ((desc[0] >> 16) |
45fa1e03eaSRoland McGrath 				((desc[1] & 0xff) << 16) |
46fa1e03eaSRoland McGrath 				(desc[1] & 0xff000000));
47fa1e03eaSRoland McGrath 
48fa1e03eaSRoland McGrath 			/* 16-bit code segment? */
49fa1e03eaSRoland McGrath 			if (!((desc[1] >> 22) & 1))
50fa1e03eaSRoland McGrath 				addr &= 0xffff;
51fa1e03eaSRoland McGrath 			addr += base;
52fa1e03eaSRoland McGrath 		}
53fa1e03eaSRoland McGrath 		mutex_unlock(&child->mm->context.lock);
54fa1e03eaSRoland McGrath 	}
55fa1e03eaSRoland McGrath 
56fa1e03eaSRoland McGrath 	return addr;
57fa1e03eaSRoland McGrath }
58fa1e03eaSRoland McGrath 
59fa1e03eaSRoland McGrath static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
60fa1e03eaSRoland McGrath {
61fa1e03eaSRoland McGrath 	int i, copied;
62fa1e03eaSRoland McGrath 	unsigned char opcode[15];
63fa1e03eaSRoland McGrath 	unsigned long addr = convert_rip_to_linear(child, regs);
64fa1e03eaSRoland McGrath 
65fa1e03eaSRoland McGrath 	copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
66fa1e03eaSRoland McGrath 	for (i = 0; i < copied; i++) {
67fa1e03eaSRoland McGrath 		switch (opcode[i]) {
68fa1e03eaSRoland McGrath 		/* popf and iret */
69fa1e03eaSRoland McGrath 		case 0x9d: case 0xcf:
70fa1e03eaSRoland McGrath 			return 1;
71fa1e03eaSRoland McGrath 
72fa1e03eaSRoland McGrath 			/* CHECKME: 64 65 */
73fa1e03eaSRoland McGrath 
74fa1e03eaSRoland McGrath 		/* opcode and address size prefixes */
75fa1e03eaSRoland McGrath 		case 0x66: case 0x67:
76fa1e03eaSRoland McGrath 			continue;
77fa1e03eaSRoland McGrath 		/* irrelevant prefixes (segment overrides and repeats) */
78fa1e03eaSRoland McGrath 		case 0x26: case 0x2e:
79fa1e03eaSRoland McGrath 		case 0x36: case 0x3e:
80fa1e03eaSRoland McGrath 		case 0x64: case 0x65:
815f76cb1fSRoland McGrath 		case 0xf0: case 0xf2: case 0xf3:
82fa1e03eaSRoland McGrath 			continue;
83fa1e03eaSRoland McGrath 
847122ec81SRoland McGrath #ifdef CONFIG_X86_64
85fa1e03eaSRoland McGrath 		case 0x40 ... 0x4f:
86fa1e03eaSRoland McGrath 			if (regs->cs != __USER_CS)
87fa1e03eaSRoland McGrath 				/* 32-bit mode: register increment */
88fa1e03eaSRoland McGrath 				return 0;
89fa1e03eaSRoland McGrath 			/* 64-bit mode: REX prefix */
90fa1e03eaSRoland McGrath 			continue;
917122ec81SRoland McGrath #endif
92fa1e03eaSRoland McGrath 
93fa1e03eaSRoland McGrath 			/* CHECKME: f2, f3 */
94fa1e03eaSRoland McGrath 
95fa1e03eaSRoland McGrath 		/*
96fa1e03eaSRoland McGrath 		 * pushf: NOTE! We should probably not let
97fa1e03eaSRoland McGrath 		 * the user see the TF bit being set. But
98fa1e03eaSRoland McGrath 		 * it's more pain than it's worth to avoid
99fa1e03eaSRoland McGrath 		 * it, and a debugger could emulate this
100fa1e03eaSRoland McGrath 		 * all in user space if it _really_ cares.
101fa1e03eaSRoland McGrath 		 */
102fa1e03eaSRoland McGrath 		case 0x9c:
103fa1e03eaSRoland McGrath 		default:
104fa1e03eaSRoland McGrath 			return 0;
105fa1e03eaSRoland McGrath 		}
106fa1e03eaSRoland McGrath 	}
107fa1e03eaSRoland McGrath 	return 0;
108fa1e03eaSRoland McGrath }
109fa1e03eaSRoland McGrath 
110fa1e03eaSRoland McGrath void user_enable_single_step(struct task_struct *child)
111fa1e03eaSRoland McGrath {
112fa1e03eaSRoland McGrath 	struct pt_regs *regs = task_pt_regs(child);
113fa1e03eaSRoland McGrath 
114fa1e03eaSRoland McGrath 	/*
115fa1e03eaSRoland McGrath 	 * Always set TIF_SINGLESTEP - this guarantees that
116fa1e03eaSRoland McGrath 	 * we single-step system calls etc..  This will also
117fa1e03eaSRoland McGrath 	 * cause us to set TF when returning to user mode.
118fa1e03eaSRoland McGrath 	 */
119fa1e03eaSRoland McGrath 	set_tsk_thread_flag(child, TIF_SINGLESTEP);
120fa1e03eaSRoland McGrath 
121fa1e03eaSRoland McGrath 	/*
122fa1e03eaSRoland McGrath 	 * If TF was already set, don't do anything else
123fa1e03eaSRoland McGrath 	 */
124fa1e03eaSRoland McGrath 	if (regs->eflags & X86_EFLAGS_TF)
125fa1e03eaSRoland McGrath 		return;
126fa1e03eaSRoland McGrath 
127fa1e03eaSRoland McGrath 	/* Set TF on the kernel stack.. */
128fa1e03eaSRoland McGrath 	regs->eflags |= X86_EFLAGS_TF;
129fa1e03eaSRoland McGrath 
130fa1e03eaSRoland McGrath 	/*
131fa1e03eaSRoland McGrath 	 * ..but if TF is changed by the instruction we will trace,
132fa1e03eaSRoland McGrath 	 * don't mark it as being "us" that set it, so that we
133fa1e03eaSRoland McGrath 	 * won't clear it by hand later.
134fa1e03eaSRoland McGrath 	 */
135fa1e03eaSRoland McGrath 	if (is_setting_trap_flag(child, regs))
136fa1e03eaSRoland McGrath 		return;
137fa1e03eaSRoland McGrath 
138*e1f28773SRoland McGrath 	set_tsk_thread_flag(child, TIF_FORCED_TF);
139fa1e03eaSRoland McGrath }
140fa1e03eaSRoland McGrath 
141fa1e03eaSRoland McGrath void user_disable_single_step(struct task_struct *child)
142fa1e03eaSRoland McGrath {
143fa1e03eaSRoland McGrath 	/* Always clear TIF_SINGLESTEP... */
144fa1e03eaSRoland McGrath 	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
145fa1e03eaSRoland McGrath 
146fa1e03eaSRoland McGrath 	/* But touch TF only if it was set by us.. */
147*e1f28773SRoland McGrath 	if (test_and_clear_tsk_thread_flag(child, TIF_FORCED_TF))
148*e1f28773SRoland McGrath 		task_pt_regs(child)->eflags &= ~X86_EFLAGS_TF;
149fa1e03eaSRoland McGrath }
150