FreeBSD/Linux Kernel Cross Reference
sys/ttd/ttd_server.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * TTD Communications parsing code for the kernel ttd server.
28 *
29 * HISTORY:
30 * $Log: ttd_server.c,v $
31 * Revision 2.2 93/05/10 23:24:51 rvb
32 * Checkin for MK80 branch.
33 * [93/05/10 15:08:55 grm]
34 *
35 * Revision 2.1.2.3 93/04/20 11:06:02 grm
36 * Changed types for use with a more universal protocol. Added code
37 * to support the use of multiple endian machines. Alignment code
38 * added.
39 * [93/04/20 grm]
40 *
41 * Revision 2.1.2.2 93/03/29 16:30:24 grm
42 * Version for protocol 2.2
43 * [93/03/29 grm]
44 *
45 * Revision 2.1.2.1 93/03/03 14:41:22 grm
46 * Second version of code. It works.
47 * [93/03/03 grm]
48 *
49 * Revision 2.1.1.8 93/01/28 15:14:51 grm
50 * Added ttd_loop_type. Last checkin before locore rewrite.
51 *
52 * Revision 2.1.1.7 93/01/22 15:52:52 grm
53 * Added request length checks.
54 *
55 * Revision 2.1.1.6 93/01/21 13:03:49 grm
56 * Changed to Ansi C prototypes. Added kttd_debug statements.
57 *
58 * Revision 2.1.1.5 92/10/30 12:44:18 grm
59 * Fixed single stepping and set_state_action bug.
60 * [92/10/30 grm]
61 *
62 * Revision 2.1.1.4 92/10/23 21:21:39 grm
63 * Added first pass at single stepping code. Fixed bug in
64 * stop/restart logic.
65 * [92/10/23 grm]
66 *
67 * Revision 2.1.1.3 92/10/08 14:29:28 grm
68 * Fixed clear_breakpoint function. Added some debugging code.
69 * [92/10/08 grm]
70 *
71 * Revision 2.1.1.2 92/10/01 15:36:54 grm
72 * KTTD restructuring checkpoint.
73 * [92/10/01 grm]
74 *
75 * Revision 2.1.1.1 92/09/25 15:10:26 grm
76 * Initial checkin.
77 * [92/09/25 grm]
78 *
79 */
80 /***********************************************************
81 Copyright 1992 by Digital Equipment Corporation, Maynard, Massachusetts,
82
83 All Rights Reserved
84
85 Permission to use, copy, modify, and distribute this software and its
86 documentation for any purpose and without fee is hereby granted, provided
87 that the above copyright notice appear in all copies and that both that
88 copyright notice and this permission notice appear in supporting
89 documentation, and that the name of Digital not be used in advertising
90 or publicity pertaining to distribution of the software without specific,
91 written prior permission. Digital makes no representations about the
92 suitability of this software for any purpose. It is provided "as is"
93 without express or implied warranty.
94
95 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
96 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
97 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
98 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
99 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
100 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
101 SOFTWARE.
102
103 ******************************************************************/
104
105 #include <mach/boolean.h>
106 #include <mach/vm_param.h>
107
108 #include <ttd/ttd_comm.h>
109 #include <ttd/ttd_types.h>
110 #include <ttd/ttd_msg.h>
111 #include <ttd/kernel_ttd.h>
112 #include <ttd/ttd_stub.h>
113 #include <ttd/ttd_server.h>
114 #include <ttd/ttd_debug.h>
115
116 struct ttd_reply prev_reply; /* saved reply for idempotency */
117 natural_t prev_reply_length;
118 ttd_operation prev_operation;
119
120 static boolean_t ttd_server_initialized;
121
122 #define END_ADDRESS(x) ((ttd_address)((natural_t)&(x) + sizeof(x)))
123
124 #define TTD_KMSG(kmsg) ((kmsg == NULL) ? ttd_request_msg : kmsg)
125
126 #define target_is_kernel(target) (target == TTD_KERNEL_MID)
127
128 #define target_stopped() kttd_target.is_stopped
129
130 #define valid_count(count) (count <= TTD_MAX_BLOCK_SIZE)
131
132 /*
133 * Aligned TTD Request.
134 */
135 struct ttd_request aligned_request;
136
137 /*
138 * Kernel target state:
139 */
140 boolean_t kttd_single_stepping = FALSE;
141 ttd_seq kttd_current_seq;
142
143 kttd_breakpoint kttd_breaktable[KTTD_MAXBPT];
144 ttd_target_info kttd_target;
145
146 ttd_machine_type ttd_target_machine_type;
147
148 /*
149 * Used by the ttd_stub code.
150 */
151 void kttd_stop_target(void)
152 {
153 kttd_target.is_stopped = TRUE;
154 }
155
156 /*
157 * Used by the machine dependent code for single stepping.
158 */
159 boolean_t break_set(ttd_address addr,
160 ttd_saved_inst *inst)
161 {
162 kttd_breakno b;
163
164 for (b = 0; b < KTTD_MAXBPT; b++) {
165 if ((!kttd_breaktable[b].free) &&
166 (kttd_breaktable[b].address == addr)) {
167 *inst = kttd_breaktable[b].saved_inst;
168 return TRUE;
169 }
170 }
171 return FALSE;
172 }
173
174 /*
175 * Misc. routines for this module:
176 */
177 static boolean_t find_break(ttd_address addr,
178 ttd_thread thread,
179 kttd_breakno *bn)
180 {
181 kttd_breakno b;
182
183 for (b = 0; b < KTTD_MAXBPT; b++) {
184 if ((!kttd_breaktable[b].free) &&
185 (kttd_breaktable[b].address == addr) &&
186 (kttd_breaktable[b].thread == thread)) {
187 *bn = b;
188 return TRUE;
189 }
190 }
191 return FALSE;
192 }
193
194 static boolean_t find_free_breakentry(kttd_breakno *breakno)
195 {
196 kttd_breakno b;
197
198 for(b = 0; b < KTTD_MAXBPT; b++) {
199 if (kttd_breaktable[b].free) {
200 *breakno = b;
201 return TRUE;
202 }
203 }
204 return FALSE;
205 }
206
207 static boolean_t valid_thread(ttd_thread thread)
208 {
209 /* XXX Fix... */
210
211 return TRUE;
212 }
213
214 static void init_break_table(void)
215 {
216 kttd_breakno bn;
217
218 for (bn = 0; bn < KTTD_MAXBPT; bn++)
219 kttd_breaktable[bn].free = TRUE;
220 }
221
222 static void init_kernel_target(void)
223 {
224 kttd_target.is_targeted = FALSE;
225 kttd_target.is_stopped = FALSE;
226 kttd_target.trapped_thread = 0;
227
228 kttd_current_seq = 0x7fffffff;
229
230 init_break_table();
231
232 kttd_single_stepping = FALSE;
233 }
234
235 /*
236 * Check to see if this message is a duplicate. Updates
237 * the current sequence number as a side effect.
238 */
239 static boolean_t duplicate(ttd_seq s)
240 {
241 boolean_t dup;
242
243 dup = (kttd_current_seq == s);
244 if (kttd_debug && (s < kttd_current_seq))
245 printf("TTD:duplicate, SRC code bites us here.\n");
246 kttd_current_seq = s;
247
248 return dup;
249 }
250
251 /*
252 * Note: since the kernel is the only kttd target, the target is
253 * implicit.
254 */
255 static void get_kernel_target_info(ttd_target_info *ti)
256 {
257 ti->is_stopped = kttd_target.is_stopped;
258 ti->is_targeted = kttd_target.is_targeted;
259 ti->trapped_thread = 1; /* XXX Fix */
260 ti->debug_reason.length = 0;
261 #if NOT_NOW
262 strcpy("Hi!", ti->debug_reason.chars);
263 #endif /* NOT_NOW */
264 }
265
266 /*******************/
267 /* Action Routines */
268 /*******************/
269
270 /*
271 * Read and write to kernel VM.
272 */
273 static ttd_code_t read_write_action(vm_prot_t access,
274 ttd_address mem_ptr,
275 ttd_address buffer,
276 ttd_count length)
277 {
278 vm_size_t size;
279
280 /*
281 * handle this in pages
282 */
283 while (length > 0) {
284 /*
285 * get the number of bytes that we can
286 * access in this page
287 */
288 size = trunc_page(mem_ptr + PAGE_SIZE) - mem_ptr;
289 if (length < size)
290 size = length;
291
292 if (!kttd_mem_access(mem_ptr, access)) {
293 if (kttd_debug)
294 printf("can't read memory\n");
295 return MemoryReferenceFailed;
296 }
297
298 /*
299 * we can move anything on this page
300 */
301 if (access & VM_PROT_WRITE) {
302 bcopy(buffer, mem_ptr, size);
303 kttd_flush_cache(mem_ptr, size);
304 }else if (access & VM_PROT_READ) {
305 bcopy(mem_ptr, buffer, size);
306 }else{
307 return InvalidArgument;
308 }
309
310 mem_ptr += size;
311 buffer += size;
312 length -= size;
313 }
314
315 return Okay;
316 }
317
318 /*
319 * XXX Fix it.
320 */
321 static boolean_t get_next_thread_action(ttd_thread *thread)
322 {
323 #if 0
324 boolean_t found_prev;
325 hardware_processor_number p;
326
327 found_prev = (*thread == 0);
328 for (p = 0; p < hardware_max_processors; p++) {
329 if (ISIN (heaP->up, p)) {
330 if (found_prev) {
331 *thread = current_thread(p);
332 return TRUE;
333 }
334 found_prev = (*thread == Current_thread(p));
335 }
336 }
337 *thread = 0;
338 return found_prev;
339 #endif
340 }
341
342 static void get_state_action(ttd_thread thread,
343 ttd_thread_info *thread_info,
344 ttd_trap_info *trap_info,
345 ttd_machine_state *machine_state)
346 {
347 /*
348 * Don't do the thread_info, or trap_info now. XXX Fix it?
349 */
350 kttd_machine_getregs(machine_state);
351 }
352
353 static void set_state_action(ttd_thread thread,
354 ttd_thread_info *thread_info,
355 ttd_trap_info *trap_info,
356 ttd_machine_state *machine_state)
357 {
358 /*
359 * Don't do the thread_info, or trap_info now either. XXX Fix it?
360 */
361
362 kttd_machine_setregs(machine_state);
363 }
364
365 static void insert_break(kttd_breakno bn,
366 ttd_address addr,
367 ttd_thread thread,
368 ttd_flavor flavor,
369 ttd_saved_inst saved_inst)
370 {
371 kttd_breaktable[bn].free = FALSE;
372 kttd_breaktable[bn].address = addr;
373 kttd_breaktable[bn].thread = thread;
374 kttd_breaktable[bn].flavor = flavor;
375 kttd_breaktable[bn].saved_inst = saved_inst;
376 }
377
378 static ttd_code_t set_break_action(ttd_address addr,
379 ttd_thread thread,
380 ttd_flavor flavor,
381 ttd_saved_inst *saved_inst)
382 {
383 kttd_breakno bn;
384 boolean_t found = FALSE;
385
386 /*
387 * Check to see if a breakpoint is already set there for a
388 * different thread.
389 */
390 for(bn = 0; bn < KTTD_MAXBPT; bn++) {
391 if (!kttd_breaktable[bn].free &&
392 (kttd_breaktable[bn].address == addr)) {
393 *saved_inst = kttd_breaktable[bn].saved_inst;
394 found = TRUE;
395 break;
396 }
397 }
398
399 /*
400 * Get a free table entry.
401 */
402 if (!find_free_breakentry(&bn))
403 return TooManyBreakpoints;
404
405 /*
406 * Insert into table if already have saved_inst.
407 */
408 if (found) {
409 insert_break(bn, addr, thread, flavor, *saved_inst);
410 return Okay;
411 }
412
413 /*
414 * Fault in memory if not available.
415 */
416 if (!kttd_mem_access(addr, VM_PROT_WRITE))
417 return MemoryReferenceFailed;
418
419 /*
420 * Insert the breakpoint into physical memory and flush the
421 * cache.
422 */
423 if (!kttd_insert_breakpoint(addr, saved_inst))
424 return MemoryReferenceFailed;
425
426 kttd_flush_cache(addr, sizeof(ttd_saved_inst));
427
428 /*
429 * Insert breakpoint into table.
430 */
431
432 insert_break(bn, addr, thread, flavor, *saved_inst);
433
434 if (kttd_debug) {
435 printf("Inserting breakpoint into table at bn = %d\n",bn);
436 }
437
438 return Okay;
439 }
440
441 static ttd_code_t clear_break_action(ttd_address addr, ttd_thread thread)
442 {
443 kttd_breakno b;
444 kttd_breakno bn = 0;
445 ttd_count count = 0;
446 ttd_saved_inst saved_inst;
447 boolean_t found = FALSE;
448
449 /*
450 * Cycle through breaktable. If more than one breakpoint
451 * at addr, we know not to replace memory with saved_inst.
452 */
453 for(b = 0; b < KTTD_MAXBPT; b++) {
454 if (!kttd_breaktable[b].free &&
455 (kttd_breaktable[b].address == addr)) {
456 if (kttd_breaktable[b].thread == thread) {
457 found = TRUE;
458 bn = b;
459 }
460 if (++count > 1) {
461 break;
462 }
463 }
464 }
465
466 /*
467 * Didn't find breakpoint in table, return
468 */
469 if (!found) {
470 if (kttd_debug) {
471 printf("Couldn't find breakpoint in table.\n");
472 }
473 return InvalidArgument;
474 }
475
476 /*
477 * Only one breakpoint at that address, fault in memory
478 * and clear the breakpoint.
479 */
480 if (count == 1) {
481 if (!kttd_mem_access(addr, VM_PROT_WRITE))
482 return MemoryReferenceFailed;
483
484 saved_inst = kttd_breaktable[bn].saved_inst;
485
486 if (!kttd_remove_breakpoint(addr, saved_inst))
487 return MemoryReferenceFailed;
488 }
489
490 /*
491 * Free entry in breaktable.
492 */
493 kttd_breaktable[bn].free = TRUE;
494
495 return Okay;
496 }
497
498 static ttd_code_t get_next_break_action(boolean_t all_breaks,
499 ttd_address *addr,
500 ttd_thread *thread,
501 ttd_flavor *flavor,
502 ttd_saved_inst *saved_inst)
503 {
504 kttd_breakno bn;
505 kttd_breakno start;
506
507 /*
508 * If addr is zero, then start from beginning of list.
509 * Otherwise, start from the breakno after addr's breakno.
510 */
511 if (*addr == 0) {
512 start = 0;
513 }else{
514 /*
515 * Find the first matching breakpoint entry.
516 */
517 for(bn = 0; bn < KTTD_MAXBPT; bn++) {
518 if (!kttd_breaktable[bn].free &&
519 (kttd_breaktable[bn].address == *addr) &&
520 (kttd_breaktable[bn].thread == *thread))
521 break;
522 }
523
524 /*
525 * If ran off the end, it's an invalid argument.
526 * Even all_breaks will have a valid addr and thread.
527 */
528 if (!all_breaks && (bn > KTTD_MAXBPT))
529 return InvalidArgument;
530
531 if (bn < KTTD_MAXBPT - 1) {
532 start = bn + 1;
533 }else{
534 /*
535 * Ran off the end. No more breakpoints
536 * in the table. Return zeros in vars.
537 */
538 *addr = 0;
539 *flavor = 0;
540 bzero(saved_inst, sizeof(ttd_saved_inst));
541 return Okay;
542 }
543 }
544
545 for(bn = start; bn < KTTD_MAXBPT; bn ++) {
546 if (!kttd_breaktable[bn].free &&
547 (all_breaks ||
548 (kttd_breaktable[bn].thread == *thread))) {
549 *addr = kttd_breaktable[bn].address;
550 *thread = kttd_breaktable[bn].thread;
551 *flavor = kttd_breaktable[bn].flavor;
552 *saved_inst = kttd_breaktable[bn].saved_inst;
553 return Okay;
554 }
555 }
556 *addr = 0;
557 *flavor = 0;
558 bzero(saved_inst, sizeof(ttd_saved_inst));
559
560 return Okay;
561 }
562
563 /*
564 * The Operations:
565 */
566
567 /*
568 * probe_server:
569 *
570 * Probe server returns the version number of the KTTD implementation
571 * and the machine type that it is executing on.
572 *
573 */
574 static void probe_server(ttd_request_t request,
575 ttd_reply_t reply,
576 ttd_address *reply_end)
577 {
578 if (kttd_debug) {
579 printf("TTD:Probe Server, version = %d, machine_type = %d\n",
580 TTD_VERSION, ttd_target_machine_type);
581 }
582
583 reply->u.probe_server.version = netswap_4_bytes(TTD_VERSION);
584 reply->u.probe_server.machine_type = netswap_4_bytes(ttd_target_machine_type);
585 *reply_end = END_ADDRESS (reply->u.probe_server);
586 }
587
588 /*
589 * get_target_info:
590 *
591 * Get target info returns the target_info struct for the given target.
592 * Since this is the kttd implementation, the only valid target is the
593 * kernel target (ie. it only returns the target info for the kernel.
594 *
595 */
596 static void get_target_info(ttd_request_t request,
597 ttd_reply_t reply,
598 ttd_address *reply_end)
599 {
600 ttd_target target;
601 ttd_target_info target_info;
602
603 target = request->u.get_target_info.target;
604 if (!target_is_kernel(target)) {
605 reply->result.code = InvalidTarget;
606
607 if (kttd_debug) {
608 printf("TTD:get_target_info, invalid target %d\n", target);
609 }
610
611 return;
612 }
613
614 get_kernel_target_info(&target_info);
615
616 reply->u.get_target_info.target_info = target_info;
617 *reply_end = END_ADDRESS (reply->u.get_target_info);
618
619 if (kttd_debug) {
620 printf("TTD:get_target_info, target %d is %s, %s, th = 0x%x\n",
621 target,
622 target_info.is_stopped ? "stopped" : "running",
623 target_info.is_targeted ? "targeted" : "untargeted",
624 target_info.trapped_thread);
625 }
626 }
627
628 /*
629 * connect_to_target:
630 *
631 * Connect to target connects to the target. The only valid target
632 * in the kttd implemetation is the kernel, all other targets are
633 * invalid. If the kernel is already targeted, it can only succeed
634 * if the key value that is passed in the request message is valid.
635 *
636 * Note: In this early implementation of kttd there is no security
637 * built into the ttd protocol (ie. a value of MASTER_KEY
638 * allows anyone to override the current connection).
639 *
640 */
641 static void connect_to_target(ttd_request_t request,
642 ttd_reply_t reply,
643 ttd_address *reply_end)
644 {
645 ttd_target target;
646 ttd_key key;
647 ttd_target_info target_info;
648
649 target = request->u.connect_to_target.target;
650 key = request->u.connect_to_target.key;
651
652 if (!target_is_kernel(target)) {
653 reply->result.code = InvalidTarget;
654 if (kttd_debug)
655 printf("TTD:connect_to_target, invalid target %d\n", target);
656 return;
657 } else if (kttd_target.is_targeted && (key != MASTER_KEY)) {
658 reply->result.code = TargetNotAvailable;
659 if (kttd_debug)
660 printf("TTD:connect_to_target, target %d unavailable\n", target);
661 return;
662 }
663
664 kttd_target.is_targeted = TRUE;
665 kttd_current_seq = 0;
666
667 get_kernel_target_info(&target_info);
668
669 reply->u.connect_to_target.target = TTD_KERNEL_MID;
670 reply->u.connect_to_target.target_info = target_info;
671 reply->result.argno = 2;
672 *reply_end = END_ADDRESS (reply->u.connect_to_target);
673
674 if (kttd_debug)
675 printf("TTD:connect_to_target, connected kttd to target %d\n",target);
676 }
677
678 /*
679 * disconnect_from_target:
680 *
681 * Disconnect from target disconnects from the specified target.
682 * The kernel target is the only valid target in the kttd implemen-
683 * tation.
684 *
685 * Note: This routine does not implicitly restart the target.
686 *
687 */
688 static void disconnect_from_target(ttd_request_t request,
689 ttd_reply_t reply,
690 ttd_address *reply_end)
691 {
692 /*
693 * The target checking is done in the kttd_service_request
694 * routine. We know the target is the kernel if we get this
695 * far.
696 */
697 kttd_target.is_targeted = FALSE;
698
699 if (kttd_debug)
700 printf("TTD:disconnect_from_target, disconnected from kttd target\n");
701 }
702
703 /*
704 * read_from_target:
705 *
706 * Read from target reads count number of bytes from the target's
707 * address space (the kernel in this implementation) and places them
708 * in the reply message's buffer.
709 *
710 */
711 static void read_from_target(ttd_request_t request,
712 ttd_reply_t reply,
713 ttd_address *reply_end)
714 {
715 ttd_address start;
716 ttd_count count;
717 ttd_address buffer;
718
719 /*
720 * Target must be stopped in order to do this operation.
721 */
722 if (!target_stopped()) {
723 reply->result.code = TargetNotStopped;
724 if (kttd_debug)
725 printf("TTD:read_from_target, target not stopped.\n");
726 return;
727 }
728
729 start = (ttd_address) request->u.read_from_target.start;
730 count = request->u.read_from_target.count;
731 buffer = (ttd_address) &reply->u.read_from_target.data[0];
732
733 if (!valid_count(count)) {
734 reply->result.code = InvalidArgument;
735 if (kttd_debug)
736 printf("TTD:read_from_target, invalid count 0x%x!!\n",
737 count);
738 return;
739 }
740
741 #if VERBOSE
742 if (kttd_debug)
743 printf("TTD:read_from_target, start= 0x%x count=0x%x,",
744 start, count);
745 #endif /* VERBOSE */
746
747 reply->result.code = read_write_action(VM_PROT_READ, start, buffer, count);
748
749 if (reply->result.code == Okay) {
750 reply->u.read_from_target.count = count;
751 *reply_end = (ttd_address)
752 &reply->u.read_from_target.data[count];
753 reply->result.argno = 2;
754
755 #if VERBOSE
756 if (kttd_debug)
757 printf("OK! readbytes=0x%x\n",count);
758 #endif /* VERBOSE */
759 }
760 }
761
762 /*
763 * write_info_target:
764 *
765 * Write into target writes count bytes into the target's address
766 * space (the kernel's address space) at the address addr from the
767 * request message's buffer.
768 *
769 */
770 static void write_into_target(ttd_request_t request,
771 ttd_reply_t reply,
772 ttd_address *reply_end)
773 {
774 ttd_address start;
775 ttd_count count;
776 ttd_address buffer;
777
778 /*
779 * Target must be stopped in order to do this operation.
780 */
781 if (!target_stopped()) {
782 reply->result.code = TargetNotStopped;
783 if (kttd_debug)
784 printf("TTD:write_into_target, target not stopped\n");
785 return;
786 }
787
788 start = (ttd_address) request->u.write_into_target.start;
789 count = request->u.write_into_target.count;
790 buffer = (ttd_address) &request->u.write_into_target.data[0];
791
792 if (!valid_count(count)) {
793 reply->result.code = InvalidArgument;
794 if (kttd_debug)
795 printf("TTD:write_into_target, invalid count 0x%x\n",
796 count);
797 return;
798 }
799
800 reply->result.code = read_write_action(VM_PROT_WRITE, start, buffer, count);
801
802 if (kttd_debug)
803 printf("TTD:write_into_target, start=0x%x count=0x%x, result = %s\n",
804 start, count, (reply->result.code == Okay) ? "OK" : "ERR");
805 }
806
807 /*
808 * get_next_thread:
809 *
810 * Get next thread returns the next thread in the taks's (target's)
811 * thread list starting at the thread in the request message. If the
812 * request thread's value is NULL, the first thread in the task's
813 * thread list is returned, otherwise we return the next thread.
814 *
815 */
816 static void get_next_thread(ttd_request_t request,
817 ttd_reply_t reply,
818 ttd_address *reply_end)
819 {
820 ttd_thread thread;
821
822 /*
823 * Target must be stopped in order to do this operation.
824 */
825 if (!target_stopped()) {
826 reply->result.code = TargetNotStopped;
827 if (kttd_debug)
828 printf("TTD:get_next_thread, target not stopped\n");
829 return;
830 }
831
832 thread = request->u.get_next_thread.thread;
833
834 if (!get_next_thread_action(&thread)) {
835 reply->result.code = InvalidArgument;
836 return;
837 }
838
839 reply->u.get_next_thread.next = thread;
840 reply->result.argno = 1;
841 *reply_end = END_ADDRESS (reply->u.get_next_thread);
842
843 if (kttd_debug)
844 printf("TTD:get_next_thread, orig= 0x%x, thread=0x%x\n",
845 request->u.get_next_thread.thread, thread);
846 }
847
848 /*
849 * get_thread_info:
850 *
851 * Get thread info returns information about the thread specified
852 * in the request message. There are three parts to the thread info:
853 *
854 * thread_info: the thread's state (ie. what's returned by
855 * thread_getstatus).
856 *
857 * trap_info: information on which trap caused the thread
858 * to trap (if it is stopped).
859 *
860 * machine_state: the thread's register state.
861 *
862 * Note: In this implementation, we only support the machine state.
863 *
864 */
865 static void get_thread_info(ttd_request_t request,
866 ttd_reply_t reply,
867 ttd_address *reply_end)
868 {
869 ttd_thread thread;
870 ttd_thread_info thread_info;
871 ttd_trap_info trap_info;
872 ttd_machine_state machine_state;
873
874 /*
875 * Target must be stopped in order to do this operation.
876 */
877 if (!target_stopped()) {
878 reply->result.code = TargetNotStopped;
879 if (kttd_debug)
880 printf("TTD:get_thread_info, target not stopped.\n");
881 return;
882 }
883
884 thread = request->u.get_thread_info.thread;
885
886 if (!valid_thread(thread)) {
887 reply->result.code = InvalidArgument;
888 if (kttd_debug)
889 printf("TTD:get_thread_info, invalid thread.\n");
890 return;
891 }
892
893 get_state_action(thread, &thread_info, &trap_info, &machine_state);
894
895 if (kttd_debug)
896 printf("TTD:get_thread_info, thread= 0x%x, ...\n", thread);
897
898 reply->u.get_thread_info.thread_info = thread_info;
899 reply->u.get_thread_info.trap_info = trap_info;
900 reply->u.get_thread_info.machine_state = machine_state;
901 reply->result.argno = 3;
902 *reply_end = END_ADDRESS (reply->u.get_thread_info);
903 }
904
905 /*
906 * set_thread_info:
907 *
908 * Set thread info sets the specified thread's three states to
909 * parameters in the request message. These thread states are the
910 * ones outlined above in the get_thread_info call.
911 *
912 * Note: Only the thread's machine_state is set in this implemen-
913 * tation.
914 *
915 */
916 static void set_thread_info(ttd_request_t request,
917 ttd_reply_t reply,
918 ttd_address *reply_end)
919 {
920 ttd_thread thread;
921 ttd_thread_info *thread_info;
922 ttd_trap_info *trap_info;
923 ttd_machine_state *machine_state;
924
925 /*
926 * Target must be stopped in order to do this operation.
927 */
928 if (!target_stopped()) {
929 reply->result.code = TargetNotStopped;
930 if (kttd_debug)
931 printf("TTD:set_thread_info, target not stopped.\n");
932 return;
933 }
934
935 #if FUTURE
936 thread = request->u.set_thread_info.thread;
937 thread_info = &(request->u.set_thread_info.thread_info);
938 trap_info = &(request->u.set_thread_info.trap_info);
939 #endif /* FUTURE */
940 machine_state = &(request->u.set_thread_info.machine_state);
941
942 #if FUTURE
943 if (!valid_thread(thread)) {
944 reply->result.code = InvalidArgument;
945 if (kttd_debug)
946 printf("TTD:set_thread_info, invalid thread.\n");
947 return;
948 }
949 #endif /* FUTURE */
950
951 set_state_action(thread, thread_info, trap_info, machine_state);
952
953 if (kttd_debug)
954 printf("TTD:set_thread_info, thread= 0x%x, ...\n");
955 }
956
957 /*
958 * stop_target:
959 *
960 * Stop target stops the target specified in the request message.
961 * In order to issue this command, the client must have successfull
962 * issued an attach_to_target request previous to this request.
963 *
964 * Note: this command was not directly supported by the original
965 * NubTTD implementation. It is supported by kttd since
966 * the kttd client can communicate with the kttd server
967 * asynchronously.
968 *
969 * Note: This implementation stops all threads in a task. Future
970 * versions will work on a per-thread basis.
971 *
972 */
973 static void stop_target(ttd_request_t request,
974 ttd_reply_t reply,
975 ttd_address *reply_end)
976 {
977 /*
978 * Return error message if already stopped.
979 */
980 if (target_stopped()) {
981 reply->result.code = TargetStopped;
982 if (kttd_debug)
983 printf("TTD:stop_target, target ALREADY stopped.\n");
984 return;
985 }
986
987 /*
988 * All we need to do to stop the kernel is call
989 * kttd_break. This will cause this "thread" to
990 * enter the kttd_handle_sync() routine which will:
991 *
992 * 1. Halt all the processors.
993 *
994 * 2. Stop the kernel (kttd_target.is_stopped = TRUE).
995 *
996 */
997
998 if (kttd_debug)
999 printf("TTD:stop_target, stopping kernel.\n");
1000
1001 kttd_halt_processors();
1002
1003 kttd_target.is_stopped = TRUE;
1004
1005 #if PRE_MIPS_CODE
1006 kttd_stop_status = FULL_STOP;
1007 #else
1008 kttd_run_status = FULL_STOP;
1009 #endif /* PRE_MIPS_CODE */
1010 }
1011
1012 /*
1013 * probe_target:
1014 *
1015 * Probe target returns the target info of the current target. This
1016 * is used extensively by the asynhronous client. In general the client
1017 * will poll the kttd target until it is stopped, and only then issue
1018 * requests.
1019 *
1020 */
1021 static void probe_target(ttd_request_t request,
1022 ttd_reply_t reply,
1023 ttd_address *reply_end)
1024 {
1025 ttd_target_info target_info;
1026
1027 get_kernel_target_info(&target_info);
1028 reply->u.probe_target.target_info = target_info;
1029 reply->result.argno = 1;
1030 *reply_end = END_ADDRESS (reply->u.probe_target);
1031
1032 if (kttd_debug)
1033 printf("TTD:probe_target, Kernel target is %s, %s, th = 0x%x\n",
1034 target_info.is_stopped ? "stopped" : "running",
1035 target_info.is_targeted ? "targeted" : "untargeted",
1036 target_info.trapped_thread);
1037 }
1038
1039 /*
1040 * restart_target:
1041 *
1042 * Restart target resume's the kttd target's (the kernel's) execution.
1043 *
1044 * Note: The current implementation restarts all a tasks threads at once.
1045 * Future versions will work on a per thread basis.
1046 *
1047 */
1048 static ttd_response_t restart_target(ttd_request_t request,
1049 ttd_reply_t reply,
1050 ttd_address *reply_end)
1051 {
1052 ttd_thread thread;
1053
1054 /*
1055 * If target already running return error code.
1056 */
1057 if (!target_stopped()) {
1058 reply->result.code = TargetNotStopped;
1059 if (kttd_debug)
1060 printf("TTD:restart_target, target not stopped.\n");
1061 return SEND_REPLY;
1062 }
1063
1064 if (kttd_debug)
1065 printf("TTD:restart_target, restarting target....\n");
1066
1067 /*
1068 * We don't need to save a message for duplicate replies since
1069 * restart doesn't send a reply. We have a check when we check
1070 * for duplicates that determines if it's a duplicate restart packet.
1071 * If it is, then we just ignore it.
1072 *
1073 * The same holds for duplicate single_step packets.
1074 */
1075
1076 /* This will make it restart. */
1077 #if PRE_MIPS_CODE
1078 kttd_stop_status = ONE_STOP;
1079 #else
1080 kttd_run_status = ONE_STOP;
1081 #endif /* PRE_MIPS_CODE */
1082
1083 kttd_target.is_stopped = FALSE;
1084
1085 #if SECOND_ATTEMPT
1086 /* Restart operations do not expect a reply. */
1087 return NO_REPLY;
1088 #else
1089 /*
1090 * Second way didn't send reply now, but third way will.
1091 * We'll cache the reply and send it whenever we receive
1092 * a duplicate! Duhhhhhh....
1093 */
1094 return SEND_REPLY;
1095 #endif /* SECOND_ATTEMPT */
1096 }
1097
1098 /*
1099 * set_breakpoint_in_target
1100 *
1101 * Set breakpoint in target sets a breakpoint for a specified thread in
1102 * in the current task's (the kernel task) at a specified address with
1103 * a specified flavor. If the thread is NULL, it applies to all threads
1104 * in the target's task (all kernel threads).
1105 *
1106 */
1107 static void set_breakpoint_in_target(ttd_request_t request,
1108 ttd_reply_t reply,
1109 ttd_address *reply_end)
1110 {
1111 ttd_address addr;
1112 ttd_thread thread;
1113 ttd_flavor flavor;
1114 kttd_breakno bn;
1115 ttd_saved_inst saved_inst;
1116
1117 /*
1118 * Target must be stopped in order to do this operation.
1119 */
1120 if (!target_stopped()) {
1121 reply->result.code = TargetNotStopped;
1122 if (kttd_debug)
1123 printf("TTD:set_breakpoint, target not stopped.\n");
1124 return;
1125 }
1126
1127 addr = (ttd_address) request->u.set_breakpoint_in_target.address;
1128 thread = (ttd_thread) request->u.set_breakpoint_in_target.thread;
1129 flavor = request->u.set_breakpoint_in_target.flavor;
1130
1131 if (thread && !valid_thread(thread)) {
1132 reply->result.code = InvalidArgument;
1133 if (kttd_debug) {
1134 printf("TTD:set_breakpoint, Invalid thread.\n");
1135 }
1136 return;
1137 }
1138
1139 if (kttd_debug) {
1140 printf("TTD:set_breakpoint, addr= 0x%x, thread= 0x%x, flavor= %d, ",
1141 addr, thread, flavor);
1142 }
1143
1144 if (find_break(addr, thread, &bn)) {
1145 kttd_breaktable[bn].flavor = flavor;
1146 saved_inst = kttd_breaktable[bn].saved_inst;
1147 }else{
1148 reply->result.code = set_break_action(addr, thread,
1149 flavor, &saved_inst);
1150 }
1151
1152 if (!reply->result.code == Okay) {
1153 if (kttd_debug)
1154 printf("ERR\n");
1155 return;
1156 }
1157
1158 if (kttd_debug)
1159 printf("OK\n");
1160
1161 reply->u.set_breakpoint_in_target.saved_inst = saved_inst;
1162 reply->result.argno = 1;
1163 *reply_end = END_ADDRESS(reply->u.set_breakpoint_in_target);
1164 }
1165
1166 /*
1167 * clear_breakpoint_in_target:
1168 *
1169 * Clear breakpoint in target removes the breakpoint from target's
1170 * breakpoint table. Like the set breakpoint request above, it takes
1171 * an address and a thread. If the thread is NULL, it only clears
1172 * the breakpoints that apply to all threads.
1173 *
1174 */
1175 static void clear_breakpoint_in_target(ttd_request_t request,
1176 ttd_reply_t reply,
1177 ttd_address *reply_end)
1178 {
1179 ttd_address addr;
1180 ttd_thread thread;
1181
1182 /*
1183 * Target must be stopped in order to do this operation.
1184 */
1185 if (!target_stopped()) {
1186 reply->result.code = TargetNotStopped;
1187 if (kttd_debug)
1188 printf("TTD:clear_break, target not stopped.\n");
1189 return;
1190 }
1191
1192 addr = (ttd_address)request->u.clear_breakpoint_in_target.address;
1193 thread = (ttd_thread)request->u.clear_breakpoint_in_target.thread;
1194
1195 if (kttd_debug)
1196 printf("TTD:clear_breakpoint, addr= 0x%x, thread= 0x%x\n",
1197 addr, thread);
1198
1199 /*
1200 * Doesn't have to be a legal thread. Might want to clear a
1201 * breakpoint for a thread that has been destroyed. The
1202 * clear break action procedure will ignore threads that don't
1203 * have breakpoints in the table.
1204 */
1205 reply->result.code = clear_break_action(addr, thread);
1206 }
1207
1208 /*
1209 * get_next_breakpoint_in_target:
1210 *
1211 * Get next breakpoint in target returns the next breakpoint in the
1212 * target's (the kernel's) breakpoint list. This request returns the
1213 * next breakpoint with respect to the breakpoint passed in the request.
1214 * If the request breakpoint is NULL, it starts at the beginning of the
1215 * breakpoint list. If all_breaks is TRUE it returns the next breakpoint
1216 * without regard to the breakpoint's associated thread. If all_breaks
1217 * is FALSE it only returns the next breakpoint that is associated with
1218 * the thread specified in the request message.
1219 *
1220 * Note: This request can be issued on a running target.
1221 *
1222 */
1223 static void get_next_breakpoint_in_target(ttd_request_t request,
1224 ttd_reply_t reply,
1225 ttd_address *reply_end)
1226 {
1227 ttd_address addr;
1228 ttd_thread thread;
1229 ttd_flavor flavor;
1230 ttd_saved_inst saved_inst;
1231 boolean_t all_breaks;
1232
1233 addr = (ttd_address)request->u.get_next_breakpoint_in_target.address;
1234 thread = (ttd_thread)request->u.get_next_breakpoint_in_target.thread;
1235 all_breaks = request->u.get_next_breakpoint_in_target.all_breaks;
1236
1237 if (kttd_debug)
1238 printf("TTD:get_break, address= 0x%x, thread= 0x%x, allbreaks= 0x%x\n",
1239 addr, thread, all_breaks);
1240
1241 reply->result.code = get_next_break_action(all_breaks, &addr, &thread,
1242 &flavor, &saved_inst);
1243
1244 if (reply->result.code != Okay)
1245 return;
1246
1247 reply->u.get_next_breakpoint_in_target.address = (ttd_address) addr;
1248 reply->u.get_next_breakpoint_in_target.flavor = flavor;
1249 reply->u.get_next_breakpoint_in_target.saved_inst = saved_inst;
1250 *reply_end = END_ADDRESS (reply->u.get_next_breakpoint_in_target);
1251 }
1252
1253 /*
1254 * kttd_single_step:
1255 *
1256 * KTTD Single Step sets the machine independent single stepping
1257 * values to single stepping state. It then calls the machine
1258 * dependent code to turn the machine into single stepping mode.
1259 *
1260 */
1261 boolean_t kttd_single_step(void)
1262 {
1263 if (kttd_single_stepping) {
1264 printf("kttd_single_step: Already Single stepping!!!\n");
1265 return FALSE;
1266 }
1267
1268 kttd_single_stepping = TRUE;
1269
1270 /*
1271 * In the current implementation, we can only set and
1272 * clear single step in the kernel task.
1273 */
1274 return(kttd_set_machine_single_step(NULL));
1275 }
1276
1277 /*
1278 * kttd_clear_single_step:
1279 *
1280 * KTTD Clear Single Step clear the machine independent single stepping
1281 * mechanism, and takes the machine out of single stepping mode.
1282 *
1283 */
1284 boolean_t kttd_clear_single_step(void)
1285 {
1286 if (!kttd_single_stepping) {
1287 printf("kttd_clear_single_step: Already out of single stepping!!\n");
1288 }
1289
1290 kttd_single_stepping = FALSE;
1291
1292 /*
1293 * In the current implementation, we can only set and
1294 * clear single step in the kernel task.
1295 */
1296 return (kttd_clear_machine_single_step(NULL));
1297 }
1298
1299 boolean_t kttd_in_single_step(void)
1300 {
1301 return (kttd_single_stepping);
1302 }
1303
1304 /*
1305 * single_step_thread:
1306 *
1307 * Single step thread starts a thread specified in the request message
1308 * executing in single step mode.
1309 *
1310 * Note: In this implementation you can only single step the current
1311 * thread.
1312 *
1313 */
1314 static ttd_response_t single_step_thread(ttd_request_t request,
1315 ttd_reply_t reply,
1316 ttd_address *reply_end)
1317 {
1318 ttd_thread thread;
1319
1320 /*
1321 * Target must be stopped in order to do this operation.
1322 */
1323 if (!target_stopped()) {
1324 reply->result.code = TargetNotStopped;
1325 if (kttd_debug)
1326 printf("TTD:single_step, target not stopped.\n");
1327 return SEND_REPLY;
1328 }
1329
1330 #if DO_LATER
1331 thread = request->u.single_step_thread.thread;
1332
1333 if (!valid_thread(thread)) {
1334 reply->result.code = InvalidArgument;
1335 return SEND_REPLY;
1336 }
1337 #endif /* DO_LATER */
1338
1339 /*
1340 * Note: in this implementation a thread is assumed to
1341 * be stopped if it's target (task) is not running,
1342 * make sure the check that the thread is stopped
1343 * when the implementation is changed to allow
1344 * thread stoppages.
1345 */
1346
1347 /*
1348 * What should happen here:
1349 *
1350 * 1. swap in the specified thread.
1351 *
1352 */
1353
1354 if (!kttd_single_step()) {
1355 reply->result.code = SingleSteppingError;
1356 if (kttd_debug)
1357 printf("TTD:single_step, single stepping ERROR!\n");
1358 return SEND_REPLY;
1359 }
1360
1361 if (kttd_debug)
1362 printf("TTD:single_step, single step.\n");
1363
1364
1365 /* This will restart the kernel */
1366 #if PRE_MIPS_CODE
1367 kttd_stop_status = ONE_STOP;
1368 #else
1369 kttd_run_status = ONE_STOP;
1370 #endif /* PRE_MIPS_CODE */
1371
1372 kttd_target.is_stopped = FALSE;
1373
1374 #if SECOND_ATTEMPT
1375 return NO_REPLY;
1376 #else
1377 /* See comments in restart_target. */
1378 return SEND_REPLY;
1379 #endif /* SECOND_ATTEMPT */
1380 }
1381
1382 /*
1383 * ttd_decode_request:
1384 *
1385 * Returns TRUE if a reply should be sent, FALSE if no reply
1386 * should be sent.
1387 *
1388 */
1389 static ttd_response_t ttd_decode_request(ttd_request_t request,
1390 ttd_reply_t reply,
1391 natural_t * reply_length)
1392 {
1393 ttd_address reply_end;
1394 boolean_t targeted_op;
1395 ttd_response_t sr;
1396
1397 /*
1398 * Convert from network to host byte ordering.
1399 */
1400 request->server = netswap_4_bytes(request->server);
1401 request->seq = netswap_4_bytes(request->seq);
1402 request->target = netswap_4_bytes(request->target);
1403 request->operation = netswap_4_bytes(request->operation);
1404
1405 targeted_op = request->operation > CONNECT_TO_TARGET;
1406
1407 /*
1408 * Setup the reply's return values that are common
1409 * to all operations:
1410 */
1411 reply->server = netswap_4_bytes(KERNEL_TTD);
1412 reply->target = netswap_4_bytes(TTD_KERNEL_MID);
1413 reply->result.code = Okay;
1414 reply->result.argno = 0;
1415 reply->operation = netswap_4_bytes(request->operation);
1416
1417 reply_end = END_ADDRESS(reply->operation);
1418
1419 /*
1420 * Set this now for those requests that return before the end.
1421 */
1422 *reply_length = (natural_t)reply_end - (natural_t)reply;
1423
1424 /*
1425 * For untargeted operations, set the sequence number of the
1426 * reply to the seq # of the last valid targeted operation.
1427 * This is used by the client end to determine restart and single
1428 * stepping reception.
1429 */
1430 reply->seq = netswap_4_bytes(kttd_current_seq);
1431
1432 if (request->server != KERNEL_TTD) {
1433 reply->result.code = ServerNotAvailable;
1434
1435 if (kttd_debug)
1436 printf("KTTD Server not available.\n");
1437
1438 return SEND_REPLY;
1439 }
1440
1441 /*
1442 * Make sure that there aren't any idempotent operations
1443 * that aren't targeted operations, since the duplicate
1444 * sequence checking takes place in this if-clause!
1445 */
1446 if (targeted_op) {
1447 if (!target_is_kernel(request->target)) {
1448 reply->result.code = InvalidTarget;
1449
1450 if (kttd_debug)
1451 printf("Invalid KTTD target.\n");
1452
1453 return SEND_REPLY;
1454 }
1455
1456 if (!kttd_target.is_targeted) {
1457 reply->result.code = TargetNotAvailable;
1458
1459 if (kttd_debug)
1460 printf("Kernel not targeted.\n");
1461
1462 return SEND_REPLY;
1463 }
1464
1465 if (duplicate(request->seq)) {
1466 #if SECOND_ATTEMPT
1467 /*
1468 * The problem is, what happens when we get a duplicate
1469 * restart or single step message? There wasn't a
1470 * reply for it, so we can't resend it. So we just
1471 * act like we're ignoring it (like we did the first
1472 * message), and "know" that we've already restarted
1473 * or single stepped the kernel.
1474 */
1475 if ((prev_operation == RESTART_TARGET) ||
1476 (prev_operation == SINGLE_STEP_THREAD))
1477 return NO_REPLY;
1478 #endif /* SECOND_ATTEMPT */
1479
1480 bcopy(&prev_reply, reply, prev_reply_length);
1481
1482 if (kttd_debug)
1483 #if KTTD_VERBOSE
1484 printf("Duplicate, resending last reply.\n");
1485 #else
1486 printf("<D>");
1487 #endif /* KTTD_VERBOSE */
1488
1489 return SEND_REPLY;
1490 }
1491 }
1492
1493 switch(request->operation) {
1494 case PROBE_SERVER:
1495 probe_server(request, reply, &reply_end);
1496 sr = SEND_REPLY;
1497 break;
1498
1499 case GET_TARGET_INFO:
1500 get_target_info(request, reply, &reply_end);
1501 sr = SEND_REPLY;
1502 break;
1503
1504 case CONNECT_TO_TARGET:
1505 connect_to_target(request, reply, &reply_end);
1506 sr = SEND_REPLY;
1507 break;
1508
1509 case DISCONNECT_FROM_TARGET:
1510 disconnect_from_target(request, reply, &reply_end);
1511 sr = SEND_REPLY;
1512 break;
1513
1514 case READ_FROM_TARGET:
1515 read_from_target(request, reply, &reply_end);
1516 sr = SEND_REPLY;
1517 break;
1518
1519 case WRITE_INTO_TARGET:
1520 write_into_target(request, reply, &reply_end);
1521 sr = SEND_REPLY;
1522 break;
1523
1524 case GET_NEXT_THREAD:
1525 get_next_thread(request, reply, &reply_end);
1526 sr = SEND_REPLY;
1527 break;
1528
1529 case GET_THREAD_INFO:
1530 get_thread_info(request, reply, &reply_end);
1531 sr = SEND_REPLY;
1532 break;
1533
1534 case SET_THREAD_INFO:
1535 set_thread_info(request, reply, &reply_end);
1536 sr = SEND_REPLY;
1537 break;
1538
1539 case STOP_TARGET:
1540 stop_target(request, reply, &reply_end);
1541 sr = SEND_REPLY;
1542 break;
1543
1544 case PROBE_TARGET:
1545 probe_target(request, reply, &reply_end);
1546 sr = SEND_REPLY;
1547 break;
1548
1549 case RESTART_TARGET:
1550 sr = restart_target(request, reply, &reply_end);
1551 break;
1552
1553 case SET_BREAKPOINT_IN_TARGET:
1554 set_breakpoint_in_target(request, reply, &reply_end);
1555 sr = SEND_REPLY;
1556 break;
1557
1558 case CLEAR_BREAKPOINT_IN_TARGET:
1559 clear_breakpoint_in_target(request, reply, &reply_end);
1560 sr = SEND_REPLY;
1561 break;
1562
1563 case GET_NEXT_BREAKPOINT_IN_TARGET:
1564 get_next_breakpoint_in_target(request, reply, &reply_end);
1565 sr = SEND_REPLY;
1566 break;
1567
1568 case SINGLE_STEP_THREAD:
1569 sr = single_step_thread(request, reply, &reply_end);
1570 break;
1571
1572 default:
1573 sr = SEND_REPLY;
1574 reply->result.code = InvalidOperation;
1575
1576 /*
1577 * Don't return here, we might've already set up our
1578 * seq # as the duplicate seq #, and we therefore need
1579 * to make sure that the prev_reply_length field is set
1580 * properly.
1581 */
1582 }
1583
1584 /*
1585 * See above comment dealing with the reply->seq.
1586 */
1587 if (targeted_op)
1588 reply->seq = netswap_4_bytes(request->seq);
1589
1590 *reply_length = (natural_t)reply_end - (natural_t)reply;
1591
1592 prev_operation = request->operation;
1593
1594 return (sr);
1595 }
1596
1597 /*
1598 * ttd_service_request:
1599 *
1600 */
1601 void ttd_service_request(void)
1602 {
1603 natural_t kttd_reply_length;
1604 ttd_request_t request;
1605 ttd_reply_t reply;
1606
1607 /*
1608 * If the length is bad, just drop the packet.
1609 */
1610 if (kttd_current_length > sizeof(struct ttd_request)) {
1611 if (kttd_debug)
1612 printf("INVALID TTD Request Size!! 0x%x > 0x%x\n",
1613 kttd_current_length, sizeof(struct ttd_request));
1614 return;
1615 }
1616
1617 request = (ttd_request_t)kttd_current_request;
1618 reply = skip_net_headers(ttd_reply_msg);
1619
1620 if ((int)request % BYTE_ALIGNMENT) {
1621 request = &aligned_request;
1622 bcopy(kttd_current_request, request,
1623 ((kttd_current_length) > sizeof(struct ttd_request) ?
1624 sizeof(struct ttd_request) : kttd_current_length));
1625 }
1626
1627 if (ttd_decode_request(request, reply, &kttd_reply_length) == SEND_REPLY) {
1628
1629 /*
1630 * We've only built the ttd_reply_msg portion of the
1631 * reply. Now build the ether/ip/udp parts and cache
1632 * the reply for duplicate retransmissions.
1633 *
1634 * Save this reply so that duplicate requests
1635 * receive the right reply (idempotent requests).
1636 *
1637 * Remember that kttd_reply_msg is the
1638 * skip_net_headers(ttd_reply_msg)!
1639 *
1640 * Just save the struct ttd_reply_msg, we'll build the
1641 * reply header and ip/udp contents later.
1642 *
1643 */
1644 bcopy(skip_net_headers(ttd_reply_msg),
1645 &prev_reply,
1646 kttd_reply_length);
1647 prev_reply_length = kttd_reply_length;
1648
1649 /*
1650 * Build the Full reply msg, then send it.
1651 */
1652
1653 complete_and_send_ttd_reply(kttd_reply_length);
1654 }
1655 }
1656
1657 void ttd_server_initialize(void)
1658 {
1659 if (ttd_server_initialized)
1660 return;
1661
1662 init_kernel_target();
1663
1664 ttd_target_machine_type = get_ttd_machine_type();
1665
1666 ttd_request_msg = &ttd_request_msg_array[0];
1667 ttd_reply_msg = &ttd_reply_msg_array[0];
1668
1669 /*
1670 * Get it to line up on the last 2 byte boundary before a
1671 * BYTE_ALIGNMENT boundary.
1672 */
1673 ttd_reply_msg = (char *)((int)ttd_reply_msg +
1674 (int)ttd_reply_msg % BYTE_ALIGNMENT +
1675 (BYTE_ALIGNMENT - 2));;
1676
1677 ttd_server_initialized = TRUE;
1678 }
Cache object: 5c7c73758b0292cd27aaeb8f4d42bb81
|