Subversion Repositories HelenOS

Rev

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

  1. /** @addtogroup generic
  2.  * @{
  3.  */
  4.  
  5. /**
  6.  * @file
  7.  * @brief   Tdebug.
  8.  */
  9.  
  10. #include <console/klog.h>
  11. #include <proc/task.h>
  12. #include <proc/thread.h>
  13. #include <arch.h>
  14. #include <errno.h>
  15. #include <ipc/ipc.h>
  16. #include <syscall/copy.h>
  17. #include <udebug/udebug.h>
  18. #include <udebug/udebug_ops.h>
  19. #include <udebug/udebug_ipc.h>
  20.  
  21. static int udebug_rp_regs_write(call_t *call, phone_t *phone)
  22. {
  23.     void *uspace_data;
  24.     unative_t to_copy;
  25.     int rc;
  26.     void *buffer;
  27.  
  28.     klog_printf("debug_regs_write()");
  29.  
  30.     uspace_data = (void *)IPC_GET_ARG3(call->data);
  31.     to_copy = IPC_GET_ARG4(call->data);
  32.     if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t);
  33.  
  34.     buffer = malloc(to_copy, 0); // ???
  35.  
  36.     rc = copy_from_uspace(buffer, uspace_data, to_copy);
  37.     if (rc != 0) {
  38.         klog_printf("debug_regs_write() - copy failed");
  39.         return rc;
  40.     }
  41.  
  42.     call->buffer = buffer;
  43.  
  44.     klog_printf(" - done");
  45.     return 0; /* No backsend */
  46. }
  47.  
  48. static int udebug_rp_mem_write(call_t *call, phone_t *phone)
  49. {
  50.     void *uspace_data;
  51.     unative_t to_copy;
  52.     int rc;
  53.     void *buffer;
  54.  
  55.     klog_printf("udebug_rp_mem_write()");
  56.  
  57.     uspace_data = (void *)IPC_GET_ARG2(call->data);
  58.     to_copy = IPC_GET_ARG4(call->data);
  59.  
  60.     buffer = malloc(to_copy, 0); // ???
  61.  
  62.     rc = copy_from_uspace(buffer, uspace_data, to_copy);
  63.     if (rc != 0) {
  64.         klog_printf(" - copy failed");
  65.         return rc;
  66.     }
  67.  
  68.     call->buffer = buffer;
  69.  
  70.     klog_printf(" - done");
  71.     return 1; /* actually need becksend with retval 0 */
  72. }
  73.  
  74.  
  75. int udebug_request_preprocess(call_t *call, phone_t *phone)
  76. {
  77.     int rc;
  78.  
  79.     switch (IPC_GET_ARG1(call->data)) {
  80.     case UDEBUG_M_REGS_WRITE:
  81.         rc = udebug_rp_regs_write(call, phone);
  82.         return rc;
  83.     case UDEBUG_M_MEM_WRITE:
  84.         rc = udebug_rp_mem_write(call, phone);
  85.         return rc;
  86.     default:
  87.         break;
  88.     }
  89.  
  90.     return 0;
  91. }
  92.  
  93. static void udebug_receive_begin(call_t *call)
  94. {
  95.     int rc;
  96.  
  97.     rc = udebug_begin(call);
  98.     if (rc < 0) {
  99.         IPC_SET_RETVAL(call->data, rc);
  100.         ipc_answer(&TASK->kernel_box, call);
  101.         return;
  102.     }
  103.  
  104.     if (rc != 0) {
  105.         IPC_SET_RETVAL(call->data, 0);
  106.         ipc_answer(&TASK->kernel_box, call);
  107.     }
  108. }
  109.  
  110. static void udebug_receive_end(call_t *call)
  111. {
  112.     int rc;
  113.  
  114.     rc = udebug_end();
  115.  
  116.     IPC_SET_RETVAL(call->data, rc);
  117.     ipc_answer(&TASK->kernel_box, call);
  118. }
  119.  
  120. static void udebug_receive_go(call_t *call)
  121. {
  122.     thread_t *t;
  123.     int rc;
  124.  
  125.     klog_printf("debug_go()");
  126.  
  127.     t = (thread_t *)IPC_GET_ARG2(call->data);
  128.  
  129.     rc = udebug_go(t, call);
  130.     if (rc < 0) {
  131.         IPC_SET_RETVAL(call->data, rc);
  132.         ipc_answer(&TASK->kernel_box, call);
  133.         return;
  134.     }
  135. }
  136.  
  137.  
  138. static void udebug_receive_thread_read(call_t *call)
  139. {
  140.     unative_t uspace_addr;
  141.     unative_t to_copy;
  142.     unsigned total_bytes;
  143.     unsigned buf_size;
  144.     void *buffer;
  145.     size_t n;
  146.     int rc;
  147.  
  148.     rc = udebug_thread_read(&buffer, &n);
  149.     if (rc < 0) {
  150.         IPC_SET_RETVAL(call->data, rc);
  151.         ipc_answer(&TASK->kernel_box, call);
  152.         return;
  153.     }
  154.  
  155.     /*
  156.      * Make use of call->buffer to transfer data to caller's userspace
  157.      */
  158.  
  159.     uspace_addr = IPC_GET_ARG2(call->data);
  160.     buf_size = IPC_GET_ARG3(call->data);
  161.  
  162.     total_bytes = n;
  163.  
  164.     if (buf_size > total_bytes)
  165.         to_copy = total_bytes;
  166.     else
  167.         to_copy = buf_size;
  168.  
  169.     IPC_SET_RETVAL(call->data, 0);
  170.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  171.        same code in process_answer() can be used
  172.        (no way to distinguish method in answer) */
  173.     IPC_SET_ARG1(call->data, uspace_addr);
  174.     IPC_SET_ARG2(call->data, to_copy);
  175.  
  176.     IPC_SET_ARG3(call->data, total_bytes);
  177.     call->buffer = buffer;
  178.  
  179.     ipc_answer(&TASK->kernel_box, call);
  180. }
  181.  
  182. static void udebug_receive_args_read(call_t *call)
  183. {
  184.     thread_t *t;
  185.     unative_t uspace_addr;
  186.     int rc;
  187.     void *buffer;
  188.  
  189.     t = (thread_t *)IPC_GET_ARG2(call->data);
  190.  
  191.     rc = udebug_args_read(t, &buffer);
  192.     if (rc != EOK) {
  193.         IPC_SET_RETVAL(call->data, rc);
  194.         ipc_answer(&TASK->kernel_box, call);
  195.         return;
  196.     }
  197.  
  198.     /*
  199.      * Make use of call->buffer to transfer data to caller's userspace
  200.      */
  201.  
  202.     uspace_addr = IPC_GET_ARG3(call->data);
  203.  
  204.     IPC_SET_RETVAL(call->data, 0);
  205.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  206.        same code in process_answer() can be used
  207.        (no way to distinguish method in answer) */
  208.     IPC_SET_ARG1(call->data, uspace_addr);
  209.     IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
  210.     call->buffer = buffer;
  211.  
  212.     ipc_answer(&TASK->kernel_box, call);
  213. }
  214.  
  215. static void udebug_receive_regs_read(call_t *call)
  216. {
  217.     thread_t *t;
  218.     unative_t uspace_addr;
  219.     unative_t to_copy;
  220.     unative_t buf_size;
  221.     unative_t total_bytes;
  222.     void *buffer;
  223.     int rc;
  224.     size_t n;
  225.  
  226.     klog_printf("debug_regs_read()");
  227.  
  228.     t = (thread_t *) IPC_GET_ARG2(call->data);
  229.  
  230.     rc = udebug_regs_read(t, &buffer, &n);
  231.     if (rc < 0) {
  232.         IPC_SET_RETVAL(call->data, rc);
  233.         ipc_answer(&TASK->kernel_box, call);
  234.         return;
  235.     }
  236.  
  237.     /*
  238.      * Make use of call->buffer to transfer data to caller's userspace
  239.      */
  240.  
  241.     uspace_addr = IPC_GET_ARG3(call->data);
  242.     buf_size = IPC_GET_ARG4(call->data);
  243.  
  244.     total_bytes = n;
  245.  
  246.     if (buf_size > total_bytes)
  247.         to_copy = total_bytes;
  248.     else
  249.         to_copy = buf_size;
  250.  
  251.     IPC_SET_RETVAL(call->data, 0);
  252.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  253.        same code in process_answer() can be used
  254.        (no way to distinguish method in answer) */
  255.     IPC_SET_ARG1(call->data, uspace_addr);
  256.     IPC_SET_ARG2(call->data, to_copy);
  257.  
  258.     IPC_SET_ARG3(call->data, total_bytes);
  259.     call->buffer = buffer;
  260.  
  261.     ipc_answer(&TASK->kernel_box, call);
  262. }
  263.  
  264. static void udebug_receive_regs_write(call_t *call)
  265. {
  266.     thread_t *t;
  267.     void *uspace_data;
  268.     unative_t to_copy;
  269.     int rc;
  270.  
  271.     uspace_data = (void *)IPC_GET_ARG3(call->data);
  272.     to_copy = IPC_GET_ARG4(call->data);
  273.  
  274.     t = (thread_t *) IPC_GET_ARG2(call->data);
  275.  
  276.     rc = udebug_regs_write(t, call->buffer);
  277.     if (rc < 0) {
  278.         IPC_SET_RETVAL(call->data, rc);
  279.         ipc_answer(&TASK->kernel_box, call);
  280.         return;
  281.     }
  282.  
  283.     /* Set answer values */
  284.  
  285.     IPC_SET_ARG1(call->data, to_copy);
  286.     IPC_SET_ARG2(call->data, sizeof(istate_t));
  287.  
  288.     IPC_SET_RETVAL(call->data, 0);
  289.     free(call->buffer);
  290.     call->buffer = NULL;
  291.  
  292.     ipc_answer(&TASK->kernel_box, call);
  293. }
  294.  
  295.  
  296. static void udebug_receive_mem_read(call_t *call)
  297. {
  298.     unative_t uspace_dst;
  299.     unative_t uspace_src;
  300.     unsigned size;
  301.     void *buffer;
  302.     int rc;
  303.  
  304.     uspace_dst = IPC_GET_ARG2(call->data);
  305.     uspace_src = IPC_GET_ARG3(call->data);
  306.     size = IPC_GET_ARG4(call->data);
  307.  
  308.     rc = udebug_mem_read(uspace_src, size, &buffer);
  309.     if (rc < 0) {
  310.         IPC_SET_RETVAL(call->data, rc);
  311.         ipc_answer(&TASK->kernel_box, call);
  312.         return;
  313.     }
  314.  
  315.     IPC_SET_RETVAL(call->data, 0);
  316.     /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
  317.        same code in process_answer() can be used
  318.        (no way to distinguish method in answer) */
  319.     IPC_SET_ARG1(call->data, uspace_dst);
  320.     IPC_SET_ARG2(call->data, size);
  321.     call->buffer = buffer;
  322.  
  323.     ipc_answer(&TASK->kernel_box, call);
  324. }
  325.  
  326. static void udebug_receive_mem_write(call_t *call)
  327. {
  328.     unative_t uspace_dst;
  329.     unsigned size;
  330.     int rc;
  331.  
  332.     klog_printf("udebug_receive_mem_write()");
  333.  
  334.     uspace_dst = IPC_GET_ARG3(call->data);
  335.     size = IPC_GET_ARG4(call->data);
  336.  
  337.     rc = udebug_mem_write(uspace_dst, call->buffer, size);
  338.     if (rc < 0) {
  339.         IPC_SET_RETVAL(call->data, rc);
  340.         ipc_answer(&TASK->kernel_box, call);
  341.         return;
  342.     }
  343.  
  344.     IPC_SET_RETVAL(call->data, 0);
  345.     free(call->buffer);
  346.     call->buffer = NULL;
  347.  
  348.     ipc_answer(&TASK->kernel_box, call);
  349. }
  350.  
  351.  
  352. /**
  353.  * Handle a debug call received on the kernel answerbox.
  354.  *
  355.  * This is called by the kbox servicing thread.
  356.  */
  357. void udebug_call_receive(call_t *call)
  358. {
  359.     int debug_method;
  360.  
  361.     debug_method = IPC_GET_ARG1(call->data);
  362.  
  363.     switch (debug_method) {
  364.     case UDEBUG_M_BEGIN:
  365.         udebug_receive_begin(call);
  366.         break;
  367.     case UDEBUG_M_END:
  368.         udebug_receive_end(call);
  369.         break;
  370.     case UDEBUG_M_GO:
  371.         udebug_receive_go(call);
  372.         break;
  373.     case UDEBUG_M_THREAD_READ:
  374.         udebug_receive_thread_read(call);
  375.         break;
  376.     case UDEBUG_M_ARGS_READ:
  377.         udebug_receive_args_read(call);
  378.         break;
  379.     case UDEBUG_M_REGS_READ:
  380.         udebug_receive_regs_read(call);
  381.         break;
  382.     case UDEBUG_M_REGS_WRITE:
  383.         udebug_receive_regs_write(call);
  384.         break;
  385.     case UDEBUG_M_MEM_READ:
  386.         udebug_receive_mem_read(call);
  387.         break;
  388.     case UDEBUG_M_MEM_WRITE:
  389.         udebug_receive_mem_write(call);
  390.         break;
  391.     }
  392. }
  393.  
  394. /** @}
  395.  */
  396.