The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ttd/ttd_server.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.