1/*
2 * Copyright 2005-2016, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <arch/user_debugger.h>
8
9#include <string.h>
10
11#include <debugger.h>
12#include <driver_settings.h>
13#include <int.h>
14#include <team.h>
15#include <thread.h>
16#include <util/AutoLock.h>
17
18
19//#define TRACE_ARCH_USER_DEBUGGER
20#ifdef TRACE_ARCH_USER_DEBUGGER
21#	define TRACE(x) dprintf x
22#else
23#	define TRACE(x) ;
24#endif
25
26#define B_NO_MORE_BREAKPOINTS				B_BUSY
27#define B_NO_MORE_WATCHPOINTS				B_BUSY
28#define B_BAD_WATCHPOINT_ALIGNMENT			B_BAD_VALUE
29#define B_WATCHPOINT_TYPE_NOT_SUPPORTED		B_NOT_SUPPORTED
30#define B_WATCHPOINT_LENGTH_NOT_SUPPORTED	B_NOT_SUPPORTED
31#define B_BREAKPOINT_NOT_FOUND				B_NAME_NOT_FOUND
32#define B_WATCHPOINT_NOT_FOUND				B_NAME_NOT_FOUND
33	// TODO: Make those real error codes.
34
35
36#ifndef __x86_64__
37extern bool gHasSSE;
38#endif
39
40// The software breakpoint instruction (int3).
41const uint8 kX86SoftwareBreakpoint[1] = { 0xcc };
42
43// maps breakpoint slot index to LEN_i LSB number
44static const size_t sDR7Len[4] = {
45	X86_DR7_LEN0_LSB, X86_DR7_LEN1_LSB, X86_DR7_LEN2_LSB, X86_DR7_LEN3_LSB
46};
47
48// maps breakpoint slot index to R/W_i LSB number
49static const size_t sDR7RW[4] = {
50	X86_DR7_RW0_LSB, X86_DR7_RW1_LSB, X86_DR7_RW2_LSB, X86_DR7_RW3_LSB
51};
52
53// maps breakpoint slot index to L_i bit number
54static const size_t sDR7L[4] = {
55	X86_DR7_L0, X86_DR7_L1, X86_DR7_L2, X86_DR7_L3
56};
57
58// maps breakpoint slot index to G_i bit number
59static const size_t sDR7G[4] = {
60	X86_DR7_G0, X86_DR7_G1, X86_DR7_G2, X86_DR7_G3
61};
62
63// maps breakpoint slot index to B_i bit number
64static const size_t sDR6B[4] = {
65	X86_DR6_B0, X86_DR6_B1, X86_DR6_B2, X86_DR6_B3
66};
67
68// Enables a hack to make single stepping work under qemu. Set via kernel
69// driver settings.
70static bool sQEmuSingleStepHack = false;
71
72
73#ifdef __x86_64__
74
75
76static void
77get_iframe_registers(const iframe* frame, debug_cpu_state* cpuState)
78{
79	// Get general purpose registers.
80	cpuState->r15 = frame->r15;
81	cpuState->r14 = frame->r14;
82	cpuState->r13 = frame->r13;
83	cpuState->r12 = frame->r12;
84	cpuState->r11 = frame->r11;
85	cpuState->r10 = frame->r10;
86	cpuState->r9 = frame->r9;
87	cpuState->r8 = frame->r8;
88	cpuState->rbp = frame->bp;
89	cpuState->rsi = frame->si;
90	cpuState->rdi = frame->di;
91	cpuState->rdx = frame->dx;
92	cpuState->rcx = frame->cx;
93	cpuState->rbx = frame->bx;
94	cpuState->rax = frame->ax;
95	cpuState->vector = frame->vector;
96	cpuState->error_code = frame->error_code;
97	cpuState->rip = frame->ip;
98	cpuState->cs = frame->cs;
99	cpuState->rflags = frame->flags;
100	cpuState->rsp = frame->sp;
101	cpuState->ss = frame->ss;
102
103	// Other segment registers are not saved or changed on interrupts, so
104	// get their value here.
105	uint16 seg;
106	__asm__ volatile ("movw %%ds, %0" : "=r" (seg));
107	cpuState->ds = seg;
108	__asm__ volatile ("movw %%es, %0" : "=r" (seg));
109	cpuState->es = seg;
110	__asm__ volatile ("movw %%fs, %0" : "=r" (seg));
111	cpuState->fs = seg;
112	__asm__ volatile ("movw %%gs, %0" : "=r" (seg));
113	cpuState->gs = seg;
114}
115
116
117static void
118set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState)
119{
120	frame->r15 = cpuState->r15;
121	frame->r14 = cpuState->r14;
122	frame->r13 = cpuState->r13;
123	frame->r12 = cpuState->r12;
124	frame->r11 = cpuState->r11;
125	frame->r10 = cpuState->r10;
126	frame->r9 = cpuState->r9;
127	frame->r8 = cpuState->r8;
128	frame->bp = cpuState->rbp;
129	frame->si = cpuState->rsi;
130	frame->di = cpuState->rdi;
131	frame->dx = cpuState->rdx;
132	frame->cx = cpuState->rcx;
133	frame->bx = cpuState->rbx;
134	frame->ax = cpuState->rax;
135	frame->ip = cpuState->rip;
136	frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS)
137		| (cpuState->rflags & X86_EFLAGS_USER_SETTABLE_FLAGS);
138	frame->sp = cpuState->rsp;
139}
140
141
142#else	// __x86_64__
143
144
145static void
146get_iframe_registers(const iframe* frame, debug_cpu_state* cpuState)
147{
148	cpuState->gs = frame->gs;
149	cpuState->fs = frame->fs;
150	cpuState->es = frame->es;
151	cpuState->ds = frame->ds;
152	cpuState->edi = frame->di;
153	cpuState->esi = frame->si;
154	cpuState->ebp = frame->bp;
155	cpuState->esp = frame->sp;
156	cpuState->ebx = frame->bx;
157	cpuState->edx = frame->orig_edx;
158	cpuState->ecx = frame->cx;
159	cpuState->eax = frame->orig_eax;
160	cpuState->vector = frame->vector;
161	cpuState->error_code = frame->error_code;
162	cpuState->eip = frame->ip;
163	cpuState->cs = frame->cs;
164	cpuState->eflags = frame->flags;
165	cpuState->user_esp = frame->user_sp;
166	cpuState->user_ss = frame->user_ss;
167}
168
169
170static void
171set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState)
172{
173//	frame->gs = cpuState->gs;
174//	frame->fs = cpuState->fs;
175//	frame->es = cpuState->es;
176//	frame->ds = cpuState->ds;
177	frame->di = cpuState->edi;
178	frame->si = cpuState->esi;
179	frame->bp = cpuState->ebp;
180//	frame->esp = cpuState->esp;
181	frame->bx = cpuState->ebx;
182	frame->dx = cpuState->edx;
183	frame->cx = cpuState->ecx;
184	frame->ax = cpuState->eax;
185//	frame->vector = cpuState->vector;
186//	frame->error_code = cpuState->error_code;
187	frame->ip = cpuState->eip;
188//	frame->cs = cpuState->cs;
189	frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS)
190		| (cpuState->eflags & X86_EFLAGS_USER_SETTABLE_FLAGS);
191	frame->user_sp = cpuState->user_esp;
192//	frame->user_ss = cpuState->user_ss;
193}
194
195
196#endif	// __x86_64__
197
198
199static void
200get_cpu_state(Thread* thread, iframe* frame, debug_cpu_state* cpuState)
201{
202	// For the floating point state to be correct the calling function must
203	// not use these registers (not even indirectly).
204#ifdef __x86_64__
205	if (frame->fpu != nullptr) {
206		memcpy(&cpuState->extended_registers, frame->fpu,
207			sizeof(cpuState->extended_registers));
208	} else {
209		memset(&cpuState->extended_registers, 0,
210			sizeof(cpuState->extended_registers));
211	}
212#else
213	Thread* thisThread = thread_get_current_thread();
214	if (gHasSSE) {
215		if (thread == thisThread) {
216			// Since fxsave requires 16-byte alignment and this isn't guaranteed
217			// for the passed buffer, we use our thread's fpu_state field as
218			// temporary buffer. We need to disable interrupts to make use of
219			// it.
220			Thread* thread = thread_get_current_thread();
221			InterruptsLocker locker;
222			x86_fxsave(thread->arch_info.fpu_state);
223				// unlike fnsave, fxsave doesn't reinit the FPU state
224		}
225		memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
226			sizeof(cpuState->extended_registers));
227	} else {
228		if (thread == thisThread) {
229			x86_fnsave(&cpuState->extended_registers);
230			// fnsave reinits the FPU state after saving, so we need to
231			// load it again
232			x86_frstor(&cpuState->extended_registers);
233		} else {
234			memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
235				sizeof(cpuState->extended_registers));
236		}
237		// TODO: Convert to fxsave format!
238	}
239#endif
240	get_iframe_registers(frame, cpuState);
241}
242
243
244static inline void
245install_breakpoints(const arch_team_debug_info& teamInfo)
246{
247	// set breakpoints
248	asm("mov %0, %%dr0" : : "r"(teamInfo.breakpoints[0].address));
249	asm("mov %0, %%dr1" : : "r"(teamInfo.breakpoints[1].address));
250	asm("mov %0, %%dr2" : : "r"(teamInfo.breakpoints[2].address));
251	asm("mov %0, %%dr3" : : "r"(teamInfo.breakpoints[3].address));
252
253	// enable breakpoints
254	asm("mov %0, %%dr7" : : "r"(teamInfo.dr7));
255}
256
257
258static inline void
259disable_breakpoints()
260{
261	asm("mov %0, %%dr7" : : "r"((size_t)X86_BREAKPOINTS_DISABLED_DR7));
262}
263
264
265/*! Sets a break-/watchpoint in the given team info.
266	Interrupts must be disabled and the team debug info lock be held.
267*/
268static inline status_t
269set_breakpoint(arch_team_debug_info& info, void* address, size_t type,
270	size_t length, bool setGlobalFlag)
271{
272	// check, if there is already a breakpoint at that address
273	bool alreadySet = false;
274	for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
275		if (info.breakpoints[i].address == address
276			&& info.breakpoints[i].type == type) {
277			alreadySet = true;
278			break;
279		}
280	}
281
282	if (!alreadySet) {
283		// find a free slot
284		int32 slot = -1;
285		for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
286			if (!info.breakpoints[i].address) {
287				slot = i;
288				break;
289			}
290		}
291
292		// init the breakpoint
293		if (slot >= 0) {
294			info.breakpoints[slot].address = address;
295			info.breakpoints[slot].type = type;
296			info.breakpoints[slot].length = length;
297
298			info.dr7 |= (length << sDR7Len[slot])
299				| (type << sDR7RW[slot])
300				| (1 << sDR7L[slot]);
301			if (setGlobalFlag)
302				info.dr7 |= (1 << sDR7G[slot]);
303		} else {
304			if (type == X86_INSTRUCTION_BREAKPOINT)
305				return B_NO_MORE_BREAKPOINTS;
306			else
307				return B_NO_MORE_WATCHPOINTS;
308		}
309	}
310
311	return B_OK;
312}
313
314
315/*! Clears a break-/watchpoint in the given team info.
316	Interrupts must be disabled and the team debug info lock be held.
317*/
318static inline status_t
319clear_breakpoint(arch_team_debug_info& info, void* address, bool watchpoint)
320{
321	// find the breakpoint
322	int32 slot = -1;
323	for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
324		if (info.breakpoints[i].address == address
325			&& (watchpoint
326				!= (info.breakpoints[i].type == X86_INSTRUCTION_BREAKPOINT))) {
327			slot = i;
328			break;
329		}
330	}
331
332	// clear the breakpoint
333	if (slot >= 0) {
334		info.breakpoints[slot].address = NULL;
335
336		info.dr7 &= ~((0x3 << sDR7Len[slot])
337			| (0x3 << sDR7RW[slot])
338			| (1 << sDR7L[slot])
339			| (1 << sDR7G[slot]));
340	} else {
341		if (watchpoint)
342			return B_WATCHPOINT_NOT_FOUND;
343		else
344			return B_BREAKPOINT_NOT_FOUND;
345	}
346
347	return B_OK;
348}
349
350
351static status_t
352set_breakpoint(void* address, size_t type, size_t length)
353{
354	if (!address)
355		return B_BAD_VALUE;
356
357	Thread* thread = thread_get_current_thread();
358
359	cpu_status state = disable_interrupts();
360	GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
361
362	status_t error = set_breakpoint(thread->team->debug_info.arch_info, address,
363		type, length, false);
364
365	RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
366	restore_interrupts(state);
367
368	return error;
369}
370
371
372static status_t
373clear_breakpoint(void* address, bool watchpoint)
374{
375	if (!address)
376		return B_BAD_VALUE;
377
378	Thread* thread = thread_get_current_thread();
379
380	cpu_status state = disable_interrupts();
381	GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
382
383	status_t error = clear_breakpoint(thread->team->debug_info.arch_info,
384		address, watchpoint);
385
386	RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
387	restore_interrupts(state);
388
389	return error;
390}
391
392
393#if KERNEL_BREAKPOINTS
394
395
396static void
397install_breakpoints_per_cpu(void* /*cookie*/, int cpu)
398{
399	Team* kernelTeam = team_get_kernel_team();
400
401	GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
402
403	install_breakpoints(kernelTeam->debug_info.arch_info);
404
405	RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
406}
407
408
409static status_t
410set_kernel_breakpoint(void* address, size_t type, size_t length)
411{
412	if (!address)
413		return B_BAD_VALUE;
414
415	Team* kernelTeam = team_get_kernel_team();
416
417	cpu_status state = disable_interrupts();
418	GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
419
420	status_t error = set_breakpoint(kernelTeam->debug_info.arch_info, address,
421		type, length, true);
422
423	RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
424
425	call_all_cpus(install_breakpoints_per_cpu, NULL);
426
427	restore_interrupts(state);
428
429	return error;
430}
431
432
433static status_t
434clear_kernel_breakpoint(void* address, bool watchpoint)
435{
436	if (!address)
437		return B_BAD_VALUE;
438
439	Team* kernelTeam = team_get_kernel_team();
440
441	cpu_status state = disable_interrupts();
442	GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
443
444	status_t error = clear_breakpoint(kernelTeam->debug_info.arch_info,
445		address, watchpoint);
446
447	RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
448
449	call_all_cpus(install_breakpoints_per_cpu, NULL);
450
451	restore_interrupts(state);
452
453	return error;
454}
455
456#endif	// KERNEL_BREAKPOINTS
457
458
459static inline status_t
460check_watch_point_parameters(void* address, uint32 type, int32 length,
461	size_t& archType, size_t& archLength)
462{
463	// check type
464	switch (type) {
465		case B_DATA_WRITE_WATCHPOINT:
466			archType = X86_DATA_WRITE_BREAKPOINT;
467			break;
468		case B_DATA_READ_WRITE_WATCHPOINT:
469			archType = X86_DATA_READ_WRITE_BREAKPOINT;
470			break;
471		case B_DATA_READ_WATCHPOINT:
472		default:
473			return B_WATCHPOINT_TYPE_NOT_SUPPORTED;
474			break;
475	}
476
477	// check length and alignment
478	switch (length) {
479		case 1:
480			archLength = X86_BREAKPOINT_LENGTH_1;
481			break;
482		case 2:
483			if ((addr_t)address & 0x1)
484				return B_BAD_WATCHPOINT_ALIGNMENT;
485			archLength = X86_BREAKPOINT_LENGTH_2;
486			break;
487		case 4:
488			if ((addr_t)address & 0x3)
489				return B_BAD_WATCHPOINT_ALIGNMENT;
490			archLength = X86_BREAKPOINT_LENGTH_4;
491			break;
492		default:
493			return B_WATCHPOINT_LENGTH_NOT_SUPPORTED;
494	}
495
496	return B_OK;
497}
498
499
500// #pragma mark - kernel debugger commands
501
502
503#if KERNEL_BREAKPOINTS
504
505static int
506debugger_breakpoints(int argc, char** argv)
507{
508	Team* kernelTeam = team_get_kernel_team();
509	arch_team_debug_info& info = kernelTeam->debug_info.arch_info;
510
511	for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
512		kprintf("breakpoint[%" B_PRId32 "] ", i);
513
514		if (info.breakpoints[i].address != NULL) {
515			kprintf("%p ", info.breakpoints[i].address);
516			switch (info.breakpoints[i].type) {
517				case X86_INSTRUCTION_BREAKPOINT:
518					kprintf("instruction");
519					break;
520				case X86_IO_READ_WRITE_BREAKPOINT:
521					kprintf("io read/write");
522					break;
523				case X86_DATA_WRITE_BREAKPOINT:
524					kprintf("data write");
525					break;
526				case X86_DATA_READ_WRITE_BREAKPOINT:
527					kprintf("data read/write");
528					break;
529			}
530
531			int length = 1;
532			switch (info.breakpoints[i].length) {
533				case X86_BREAKPOINT_LENGTH_1:
534					length = 1;
535					break;
536				case X86_BREAKPOINT_LENGTH_2:
537					length = 2;
538					break;
539				case X86_BREAKPOINT_LENGTH_4:
540					length = 4;
541					break;
542			}
543
544			if (info.breakpoints[i].type != X86_INSTRUCTION_BREAKPOINT)
545				kprintf(" %d byte%s", length, (length > 1 ? "s" : ""));
546		} else
547			kprintf("unused");
548
549		kprintf("\n");
550	}
551
552	return 0;
553}
554
555
556static int
557debugger_breakpoint(int argc, char** argv)
558{
559	// get arguments
560
561	if (argc < 2 || argc > 3)
562		return print_debugger_command_usage(argv[0]);
563
564	addr_t address = strtoul(argv[1], NULL, 0);
565	if (address == 0)
566		return print_debugger_command_usage(argv[0]);
567
568	bool clear = false;
569	if (argc == 3) {
570		if (strcmp(argv[2], "clear") == 0)
571			clear = true;
572		else
573			return print_debugger_command_usage(argv[0]);
574	}
575
576	// set/clear breakpoint
577
578	arch_team_debug_info& info = team_get_kernel_team()->debug_info.arch_info;
579
580	status_t error;
581
582	if (clear) {
583		error = clear_breakpoint(info, (void*)address, false);
584	} else {
585		error = set_breakpoint(info, (void*)address, X86_INSTRUCTION_BREAKPOINT,
586			X86_BREAKPOINT_LENGTH_1, true);
587	}
588
589	if (error == B_OK)
590		call_all_cpus_sync(install_breakpoints_per_cpu, NULL);
591	else
592		kprintf("Failed to install breakpoint: %s\n", strerror(error));
593
594	return 0;
595}
596
597
598static int
599debugger_watchpoint(int argc, char** argv)
600{
601	// get arguments
602
603	if (argc < 2 || argc > 4)
604		return print_debugger_command_usage(argv[0]);
605
606	addr_t address = strtoul(argv[1], NULL, 0);
607	if (address == 0)
608		return print_debugger_command_usage(argv[0]);
609
610	bool clear = false;
611	bool readWrite = false;
612	int argi = 2;
613	int length = 1;
614	if (argc >= 3) {
615		if (strcmp(argv[argi], "clear") == 0) {
616			clear = true;
617			argi++;
618		} else if (strcmp(argv[argi], "rw") == 0) {
619			readWrite = true;
620			argi++;
621		}
622
623		if (!clear && argi < argc)
624			length = strtoul(argv[argi++], NULL, 0);
625
626		if (length == 0 || argi < argc)
627			return print_debugger_command_usage(argv[0]);
628	}
629
630	// set/clear breakpoint
631
632	arch_team_debug_info& info = team_get_kernel_team()->debug_info.arch_info;
633
634	status_t error;
635
636	if (clear) {
637		error = clear_breakpoint(info, (void*)address, true);
638	} else {
639		uint32 type = readWrite ? B_DATA_READ_WRITE_WATCHPOINT
640			: B_DATA_WRITE_WATCHPOINT;
641
642		size_t archType, archLength;
643		error = check_watch_point_parameters((void*)address, type, length,
644			archType, archLength);
645
646		if (error == B_OK) {
647			error = set_breakpoint(info, (void*)address, archType, archLength,
648				true);
649		}
650	}
651
652	if (error == B_OK)
653		call_all_cpus_sync(install_breakpoints_per_cpu, NULL);
654	else
655		kprintf("Failed to install breakpoint: %s\n", strerror(error));
656
657	return 0;
658}
659
660
661static int
662debugger_single_step(int argc, char** argv)
663{
664	// TODO: Since we need an iframe, this doesn't work when KDL wasn't entered
665	// via an exception.
666
667	iframe* frame = x86_get_current_iframe();
668	if (frame == NULL) {
669		kprintf("Failed to get the current iframe!\n");
670		return 0;
671	}
672
673	frame->flags |= (1 << X86_EFLAGS_TF);
674
675	return B_KDEBUG_QUIT;
676}
677
678
679#endif	// KERNEL_BREAKPOINTS
680
681
682// #pragma mark - in-kernel public interface
683
684
685void
686arch_clear_team_debug_info(arch_team_debug_info* info)
687{
688	for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++)
689		info->breakpoints[i].address = NULL;
690
691	info->dr7 = X86_BREAKPOINTS_DISABLED_DR7;
692}
693
694
695void
696arch_destroy_team_debug_info(arch_team_debug_info* info)
697{
698	arch_clear_team_debug_info(info);
699}
700
701
702void
703arch_clear_thread_debug_info(arch_thread_debug_info* info)
704{
705	info->flags = 0;
706}
707
708
709void
710arch_destroy_thread_debug_info(arch_thread_debug_info* info)
711{
712	arch_clear_thread_debug_info(info);
713}
714
715
716void
717arch_update_thread_single_step()
718{
719	if (iframe* frame = x86_get_user_iframe()) {
720		Thread* thread = thread_get_current_thread();
721
722		// set/clear TF in EFLAGS depending on whether single stepping is
723		// desired
724		if (thread->debug_info.flags & B_THREAD_DEBUG_SINGLE_STEP)
725			frame->flags |= (1 << X86_EFLAGS_TF);
726		else
727			frame->flags &= ~(1 << X86_EFLAGS_TF);
728	}
729}
730
731
732void
733arch_set_debug_cpu_state(const debug_cpu_state* cpuState)
734{
735	if (iframe* frame = x86_get_user_iframe()) {
736		// For the floating point state to be correct the calling function must
737		// not use these registers (not even indirectly).
738#ifdef __x86_64__
739		Thread* thread = thread_get_current_thread();
740		memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers,
741			sizeof(cpuState->extended_registers));
742		frame->fpu = &thread->arch_info.fpu_state;
743#else
744		if (gHasSSE) {
745			// Since fxrstor requires 16-byte alignment and this isn't
746			// guaranteed passed buffer, we use our thread's fpu_state field as
747			// temporary buffer. We need to disable interrupts to make use of
748			// it.
749			Thread* thread = thread_get_current_thread();
750			InterruptsLocker locker;
751			memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers,
752				sizeof(cpuState->extended_registers));
753			x86_fxrstor(thread->arch_info.fpu_state);
754		} else {
755			// TODO: Implement! We need to convert the format first.
756//			x86_frstor(&cpuState->extended_registers);
757		}
758#endif
759		set_iframe_registers(frame, cpuState);
760	}
761}
762
763
764void
765arch_get_debug_cpu_state(debug_cpu_state* cpuState)
766{
767	if (iframe* frame = x86_get_user_iframe())
768		get_cpu_state(thread_get_current_thread(), frame, cpuState);
769}
770
771
772/*!	\brief Retrieves the CPU state for the given thread.
773	The thread must not be running and the thread's scheduler spinlock must be
774	held.
775	\param thread The thread whose CPU state to retrieve.
776	\param cpuState Pointer to pre-allocated storage for the CPU state.
777	\return \c B_OK, if everything goes fine, another error code, if the CPU
778		state could not be retrieved.
779*/
780status_t
781arch_get_thread_debug_cpu_state(Thread* thread, debug_cpu_state* cpuState)
782{
783	iframe* frame = x86_get_thread_user_iframe(thread);
784	if (frame == NULL)
785		return B_BAD_VALUE;
786
787	get_cpu_state(thread, frame, cpuState);
788	return B_OK;
789}
790
791
792status_t
793arch_set_breakpoint(void* address)
794{
795	return set_breakpoint(address, X86_INSTRUCTION_BREAKPOINT,
796		X86_BREAKPOINT_LENGTH_1);
797}
798
799
800status_t
801arch_clear_breakpoint(void* address)
802{
803	return clear_breakpoint(address, false);
804}
805
806
807status_t
808arch_set_watchpoint(void* address, uint32 type, int32 length)
809{
810	size_t archType, archLength;
811	status_t error = check_watch_point_parameters(address, type, length,
812		archType, archLength);
813	if (error != B_OK)
814		return error;
815
816	return set_breakpoint(address, archType, archLength);
817}
818
819
820status_t
821arch_clear_watchpoint(void* address)
822{
823	return clear_breakpoint(address, true);
824}
825
826
827bool
828arch_has_breakpoints(arch_team_debug_info* info)
829{
830	// Reading info->dr7 is atomically, so we don't need to lock. The caller
831	// has to ensure, that the info doesn't go away.
832	return (info->dr7 != X86_BREAKPOINTS_DISABLED_DR7);
833}
834
835
836#if KERNEL_BREAKPOINTS
837
838status_t
839arch_set_kernel_breakpoint(void* address)
840{
841	status_t error = set_kernel_breakpoint(address, X86_INSTRUCTION_BREAKPOINT,
842		X86_BREAKPOINT_LENGTH_1);
843
844	if (error != B_OK) {
845		panic("arch_set_kernel_breakpoint() failed to set breakpoint: %s",
846			strerror(error));
847	}
848
849	return error;
850}
851
852
853status_t
854arch_clear_kernel_breakpoint(void* address)
855{
856	status_t error = clear_kernel_breakpoint(address, false);
857
858	if (error != B_OK) {
859		panic("arch_clear_kernel_breakpoint() failed to clear breakpoint: %s",
860			strerror(error));
861	}
862
863	return error;
864}
865
866
867status_t
868arch_set_kernel_watchpoint(void* address, uint32 type, int32 length)
869{
870	size_t archType, archLength;
871	status_t error = check_watch_point_parameters(address, type, length,
872		archType, archLength);
873
874	if (error == B_OK)
875		error = set_kernel_breakpoint(address, archType, archLength);
876
877	if (error != B_OK) {
878		panic("arch_set_kernel_watchpoint() failed to set watchpoint: %s",
879			strerror(error));
880	}
881
882	return error;
883}
884
885
886status_t
887arch_clear_kernel_watchpoint(void* address)
888{
889	status_t error = clear_kernel_breakpoint(address, true);
890
891	if (error != B_OK) {
892		panic("arch_clear_kernel_watchpoint() failed to clear watchpoint: %s",
893			strerror(error));
894	}
895
896	return error;
897}
898
899#endif	// KERNEL_BREAKPOINTS
900
901
902// #pragma mark - x86 implementation interface
903
904
905/**
906 *	Interrupts are disabled. \a frame is unused, i.e. can be \c NULL.
907 */
908void
909x86_init_user_debug_at_kernel_exit(iframe* frame)
910{
911	Thread* thread = thread_get_current_thread();
912
913	if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_DEFINED))
914		return;
915
916	// disable kernel breakpoints
917	disable_breakpoints();
918
919	// install the user breakpoints
920	GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
921
922	arch_team_debug_info &teamInfo = thread->team->debug_info.arch_info;
923
924	install_breakpoints(teamInfo);
925
926	atomic_or(&thread->flags, THREAD_FLAGS_BREAKPOINTS_INSTALLED);
927
928	RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
929}
930
931
932/**
933 *	Interrupts are disabled.
934 */
935void
936x86_exit_user_debug_at_kernel_entry()
937{
938	Thread* thread = thread_get_current_thread();
939
940	// We need to save the current values of dr6 and dr7 in the CPU structure,
941	// since in case of a debug exception we might overwrite them before
942	// x86_handle_debug_exception() is called. Debug exceptions occur when
943	// hitting a hardware break/watchpoint or when single-stepping.
944	asm("mov %%dr6, %0" : "=r"(thread->cpu->arch.dr6));
945	asm("mov %%dr7, %0" : "=r"(thread->cpu->arch.dr7));
946
947	// The remainder needs only be done, when user breakpoints are installed.
948	if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED))
949		return;
950
951	// disable user breakpoints
952	disable_breakpoints();
953
954	// install kernel breakpoints
955	Team* kernelTeam = team_get_kernel_team();
956
957	GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
958
959	install_breakpoints(kernelTeam->debug_info.arch_info);
960
961	atomic_and(&thread->flags, ~THREAD_FLAGS_BREAKPOINTS_INSTALLED);
962
963	RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info);
964}
965
966
967/**
968 *	Interrupts are disabled and will possibly be enabled by the function.
969 */
970void
971x86_handle_debug_exception(iframe* frame)
972{
973	Thread* thread = thread_get_current_thread();
974
975	// Get dr6 and dr7. If the given iframe is a userland frame, the exception
976	// obviously occurred in userland. In that case
977	// x86_exit_user_debug_at_kernel_entry() has already been invoked and dr6
978	// and dr7 are stored in the cpu info. Otherwise we need to fetch the
979	// current values from the registers.
980	size_t dr6;
981	size_t dr7;
982	if (IFRAME_IS_USER(frame)) {
983		dr6 = thread->cpu->arch.dr6;
984		dr7 = thread->cpu->arch.dr7;
985	} else {
986		asm("mov %%dr6, %0" : "=r"(dr6));
987		asm("mov %%dr7, %0" : "=r"(dr7));
988	}
989
990	TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7));
991
992	// check, which exception condition applies
993	if (dr6 & X86_DR6_BREAKPOINT_MASK) {
994		// breakpoint
995
996		// check which breakpoint was taken
997		bool watchpoint = true;
998		for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
999			if (dr6 & (1 << sDR6B[i])) {
1000				size_t type = (dr7 >> sDR7RW[i]) & 0x3;
1001				if (type == X86_INSTRUCTION_BREAKPOINT)
1002					watchpoint = false;
1003			}
1004		}
1005
1006		if (IFRAME_IS_USER(frame)) {
1007			// enable interrupts and notify the debugger
1008			enable_interrupts();
1009
1010			if (watchpoint)
1011				user_debug_watchpoint_hit();
1012			else
1013				user_debug_breakpoint_hit(false);
1014		} else {
1015			panic("hit kernel %spoint: dr6: 0x%lx, dr7: 0x%lx",
1016				watchpoint ? "watch" : "break", dr6, dr7);
1017		}
1018	} else if (dr6 & (1 << X86_DR6_BD)) {
1019		// general detect exception
1020		// Occurs only, if GD in DR7 is set (which we don't do) and someone
1021		// tries to write to the debug registers.
1022		if (IFRAME_IS_USER(frame)) {
1023			dprintf("x86_handle_debug_exception(): ignoring spurious general "
1024				"detect exception\n");
1025
1026			enable_interrupts();
1027		} else
1028			panic("spurious general detect exception in kernel mode");
1029	} else if ((dr6 & (1 << X86_DR6_BS)) || sQEmuSingleStepHack) {
1030		// single step
1031
1032		if (IFRAME_IS_USER(frame)) {
1033			// enable interrupts and notify the debugger
1034			enable_interrupts();
1035
1036			user_debug_single_stepped();
1037		} else {
1038			// Disable single-stepping -- the next "step" command will re-enable
1039			// it, but we don't want it when continuing otherwise.
1040			frame->flags &= ~(1 << X86_EFLAGS_TF);
1041
1042			// Determine whether the exception occurred at a syscall/trap
1043			// kernel entry or whether this is genuine kernel single-stepping.
1044			bool inKernel = true;
1045			if (thread->team != team_get_kernel_team()
1046				&& x86_get_user_iframe() == NULL) {
1047				// TODO: This is not yet fully correct, since a newly created
1048				// thread that hasn't entered userland yet also has this
1049				// property.
1050				inKernel = false;
1051			}
1052
1053			if (inKernel) {
1054				panic("kernel single step");
1055			} else {
1056				// The thread is a userland thread and it just entered the
1057				// kernel when the single-step exception occurred. This happens
1058				// e.g. when sysenter is called with single-stepping enabled.
1059				// We need to ignore the exception now and send a single-step
1060				// notification later, when the thread wants to return from the
1061				// kernel.
1062				InterruptsSpinLocker threadDebugInfoLocker(
1063					thread->debug_info.lock);
1064
1065				// Check whether the team is still being debugged and set
1066				// the B_THREAD_DEBUG_NOTIFY_SINGLE_STEP and
1067				// B_THREAD_DEBUG_STOP flags, so that the thread will be
1068				// stopped when it is going to leave the kernel and notify the
1069				// debugger about the single-step event.
1070				int32 teamDebugFlags
1071					= atomic_get(&thread->team->debug_info.flags);
1072				if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
1073					atomic_or(&thread->debug_info.flags,
1074						B_THREAD_DEBUG_NOTIFY_SINGLE_STEP
1075							| B_THREAD_DEBUG_STOP);
1076
1077					// also set the respective thread flag
1078					atomic_or(&thread->flags, THREAD_FLAGS_DEBUG_THREAD);
1079				}
1080			}
1081		}
1082	} else if (dr6 & (1 << X86_DR6_BT)) {
1083		// task switch
1084		// Occurs only, if T in EFLAGS is set (which we don't do).
1085		if (IFRAME_IS_USER(frame)) {
1086			dprintf("x86_handle_debug_exception(): ignoring spurious task switch "
1087				"exception\n");
1088
1089			enable_interrupts();
1090		} else
1091			panic("spurious task switch exception in kernel mode");
1092	} else {
1093		if (IFRAME_IS_USER(frame)) {
1094			TRACE(("x86_handle_debug_exception(): ignoring spurious debug "
1095				"exception (no condition recognized)\n"));
1096
1097			enable_interrupts();
1098		} else {
1099			panic("spurious debug exception in kernel mode (no condition "
1100				"recognized)");
1101		}
1102	}
1103}
1104
1105
1106/**
1107 *	Interrupts are disabled and will possibly be enabled by the function.
1108 */
1109void
1110x86_handle_breakpoint_exception(iframe* frame)
1111{
1112	TRACE(("x86_handle_breakpoint_exception()\n"));
1113
1114	// reset eip to the int3 instruction
1115	frame->ip--;
1116
1117	if (!IFRAME_IS_USER(frame)) {
1118		panic("breakpoint exception in kernel mode");
1119		return;
1120	}
1121
1122	enable_interrupts();
1123
1124	user_debug_breakpoint_hit(true);
1125}
1126
1127
1128void
1129x86_init_user_debug()
1130{
1131	// get debug settings
1132	if (void* handle = load_driver_settings("kernel")) {
1133		sQEmuSingleStepHack = get_driver_boolean_parameter(handle,
1134			"qemu_single_step_hack", false, false);;
1135
1136		unload_driver_settings(handle);
1137	}
1138
1139#if KERNEL_BREAKPOINTS
1140	// install debugger commands
1141	add_debugger_command_etc("breakpoints", &debugger_breakpoints,
1142		"Lists current break-/watchpoints",
1143		"\n"
1144		"Lists the current kernel break-/watchpoints.\n", 0);
1145	add_debugger_command_alias("watchpoints", "breakpoints", NULL);
1146	add_debugger_command_etc("breakpoint", &debugger_breakpoint,
1147		"Set/clears a breakpoint",
1148		"<address> [ clear ]\n"
1149		"Sets respectively clears the breakpoint at address <address>.\n", 0);
1150	add_debugger_command_etc("watchpoint", &debugger_watchpoint,
1151		"Set/clears a watchpoint",
1152		"<address> <address> ( [ rw ] [ <size> ] | clear )\n"
1153		"Sets respectively clears the watchpoint at address <address>.\n"
1154		"If \"rw\" is given the new watchpoint is a read/write watchpoint\n"
1155		"otherwise a write watchpoint only.\n", 0);
1156	add_debugger_command_etc("step", &debugger_single_step,
1157		"Single-steps to the next instruction",
1158		"\n"
1159		"Single-steps to the next instruction.\n", 0);
1160#endif
1161}
1162
1163