Subversion Repositories HelenOS

Rev

Rev 3441 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup generic
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file
  35.  * @brief   Udebug IPC message handling.
  36.  */
  37.  
  38. #include <print.h>
  39. #include <proc/task.h>
  40. #include <proc/thread.h>
  41. #include <arch.h>
  42. #include <errno.h>
  43. #include <ipc/ipc.h>
  44. #include <syscall/copy.h>
  45. #include <udebug/udebug.h>
  46. #include <udebug/udebug_ops.h>
  47. #include <udebug/udebug_ipc.h>
  48.  
  49. int udebug_request_preprocess(call_t *call, phone_t *phone)
  50. {
  51.     switch (IPC_GET_ARG1(call->data)) {
  52.     /* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
  53.     default:
  54.         break;
  55.     }
  56.  
  57.     return 0;
  58. }
  59.  
  60. static void udebug_receive_begin(call_t *call)
  61. {
  62.     int rc;
  63.  
  64.     rc = udebug_begin(call);
  65.     if (rc < 0) {
  66.         IPC_SET_RETVAL(call->data, rc);
  67.         ipc_answer(&TASK->kernel_box, call);
  68.         return;
  69.     }
  70.  
  71.     if (rc != 0) {
  72.         IPC_SET_RETVAL(call->data, 0);
  73.         ipc_answer(&TASK->kernel_box, call);
  74.     }
  75. }
  76.  
  77. static void udebug_receive_end(call_t *call)
  78. {
  79.     int rc;
  80.  
  81.     rc = udebug_end();
  82.  
  83.     IPC_SET_RETVAL(call->data, rc);
  84.     ipc_answer(&TASK->kernel_box, call);
  85. }
  86.  
  87. static void udebug_receive_set_evmask(call_t *call)
  88. {
  89.     int rc;
  90.     udebug_evmask_t mask;
  91.  
  92.     mask = IPC_GET_ARG2(call->data);
  93.     rc = udebug_set_evmask(mask);
  94.  
  95.     IPC_SET_RETVAL(call->data, rc);
  96.     ipc_answer(&TASK->kernel_box, call);
  97. }
  98.  
  99.  
  100. static void udebug_receive_go(call_t *call)
  101. {
  102.     thread_t *t;
  103.     int rc;
  104.  
  105.     //printf("debug_go()\n");
  106.  
  107.     t = (thread_t *)IPC_GET_ARG2(call->data);
  108.  
  109.     rc = udebug_go(t, call);
  110.     if (rc < 0) {
  111.         IPC_SET_RETVAL(call->data, rc);
  112.         ipc_answer(&TASK->kernel_box, call);
  113.         return;
  114.     }
  115. }
  116.  
  117. static void udebug_receive_stop(call_t *call)
  118. {
  119.     thread_t *t;
  120.     int rc;
  121.  
  122.     printf("debug_stop()\n");
  123.  
  124.     t = (thread_t *)IPC_GET_ARG2(call->data);
  125.  
  126.     rc = udebug_stop(t, call);
  127.     IPC_SET_RETVAL(call->data, rc);
  128.     ipc_answer(&TASK->kernel_box, call);
  129. }
  130.  
  131. static void udebug_receive_thread_read(call_t *call)
  132. {
  133.     unative_t uspace_addr;
  134.     unative_t to_copy;
  135.     unsigned total_bytes;
  136.     unsigned buf_size;
  137.     void *buffer;
  138.     size_t n;
  139.     int rc;
  140.  
  141.     uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
  142.     buf_size = IPC_GET_ARG3(call->data);    /* Dest. buffer size */
  143.  
  144.     /*
  145.      * Read thread list. Variable n will be filled with actual number
  146.      * of threads times thread-id size.
  147.      */
  148.     rc = udebug_thread_read(&buffer, buf_size, &n);
  149.     if (rc < 0) {
  150.         IPC_SET_RETVAL(call->data, rc);
  151.         ipc_answer(&TASK->kernel_box, call);
  152.         return;
  153.     }
  154.  
  155.     total_bytes = n;
  156.  
  157.     /* Copy MAX(buf_size, total_bytes) bytes */
  158.  
  159.     if (buf_size > total_bytes)
  160.         to_copy = total_bytes;
  161.     else
  162.         to_copy = buf_size;
  163.  
  164.     /*
  165.      * Make use of call->buffer to transfer data to caller's userspace
  166.      */
  167.  
  168.     IPC_SET_RETVAL(call->data, 0);
  169.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  170.        same code in process_answer() can be used
  171.        (no way to distinguish method in answer) */
  172.     IPC_SET_ARG1(call->data, uspace_addr);
  173.     IPC_SET_ARG2(call->data, to_copy);
  174.  
  175.     IPC_SET_ARG3(call->data, total_bytes);
  176.     call->buffer = buffer;
  177.  
  178.     ipc_answer(&TASK->kernel_box, call);
  179. }
  180.  
  181. static void udebug_receive_args_read(call_t *call)
  182. {
  183.     thread_t *t;
  184.     unative_t uspace_addr;
  185.     int rc;
  186.     void *buffer;
  187.  
  188.     t = (thread_t *)IPC_GET_ARG2(call->data);
  189.  
  190.     rc = udebug_args_read(t, &buffer);
  191.     if (rc != EOK) {
  192.         IPC_SET_RETVAL(call->data, rc);
  193.         ipc_answer(&TASK->kernel_box, call);
  194.         return;
  195.     }
  196.  
  197.     /*
  198.      * Make use of call->buffer to transfer data to caller's userspace
  199.      */
  200.  
  201.     uspace_addr = IPC_GET_ARG3(call->data);
  202.  
  203.     IPC_SET_RETVAL(call->data, 0);
  204.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  205.        same code in process_answer() can be used
  206.        (no way to distinguish method in answer) */
  207.     IPC_SET_ARG1(call->data, uspace_addr);
  208.     IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
  209.     call->buffer = buffer;
  210.  
  211.     ipc_answer(&TASK->kernel_box, call);
  212. }
  213.  
  214. static void udebug_receive_mem_read(call_t *call)
  215. {
  216.     unative_t uspace_dst;
  217.     unative_t uspace_src;
  218.     unsigned size;
  219.     void *buffer;
  220.     int rc;
  221.  
  222.     uspace_dst = IPC_GET_ARG2(call->data);
  223.     uspace_src = IPC_GET_ARG3(call->data);
  224.     size = IPC_GET_ARG4(call->data);
  225.  
  226.     rc = udebug_mem_read(uspace_src, size, &buffer);
  227.     if (rc < 0) {
  228.         IPC_SET_RETVAL(call->data, rc);
  229.         ipc_answer(&TASK->kernel_box, call);
  230.         return;
  231.     }
  232.  
  233.     IPC_SET_RETVAL(call->data, 0);
  234.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  235.        same code in process_answer() can be used
  236.        (no way to distinguish method in answer) */
  237.     IPC_SET_ARG1(call->data, uspace_dst);
  238.     IPC_SET_ARG2(call->data, size);
  239.     call->buffer = buffer;
  240.  
  241.     ipc_answer(&TASK->kernel_box, call);
  242. }
  243.  
  244. /**
  245.  * Handle a debug call received on the kernel answerbox.
  246.  *
  247.  * This is called by the kbox servicing thread.
  248.  */
  249. void udebug_call_receive(call_t *call)
  250. {
  251.     int debug_method;
  252.  
  253.     debug_method = IPC_GET_ARG1(call->data);
  254.  
  255.     if (debug_method != UDEBUG_M_BEGIN) {
  256.         /*
  257.          * Verify that the sender is this task's debugger.
  258.          * Note that this is the only thread that could change
  259.          * TASK->debugger. Therefore no locking is necessary
  260.          * and the sender can be safely considered valid until
  261.          * control exits this function.
  262.          */
  263.         if (TASK->udebug.debugger != call->sender) {
  264.             IPC_SET_RETVAL(call->data, EINVAL);
  265.             ipc_answer(&TASK->kernel_box, call);
  266.             return;
  267.         }
  268.     }
  269.  
  270.     switch (debug_method) {
  271.     case UDEBUG_M_BEGIN:
  272.         udebug_receive_begin(call);
  273.         break;
  274.     case UDEBUG_M_END:
  275.         udebug_receive_end(call);
  276.         break;
  277.     case UDEBUG_M_SET_EVMASK:
  278.         udebug_receive_set_evmask(call);
  279.         break;
  280.     case UDEBUG_M_GO:
  281.         udebug_receive_go(call);
  282.         break;
  283.     case UDEBUG_M_STOP:
  284.         udebug_receive_stop(call);
  285.         break;
  286.     case UDEBUG_M_THREAD_READ:
  287.         udebug_receive_thread_read(call);
  288.         break;
  289.     case UDEBUG_M_ARGS_READ:
  290.         udebug_receive_args_read(call);
  291.         break;
  292.     case UDEBUG_M_MEM_READ:
  293.         udebug_receive_mem_read(call);
  294.         break;
  295.     }
  296. }
  297.  
  298. /** @}
  299.  */
  300.