OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [adv_jtag_bridge/] [hwp_server.c] - Blame information for rev 59

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 51 nyawn
/* hwp_server.c -- Server for hardware watchpoint handling
2
   Copyright(C) 2010 Nathan Yawn <nyawn@opencores.org>
3
 
4
   This file is part the advanced debug unit / bridge.  GDB does not
5
   have support for the OR1200's advanced hardware watchpoints.  This
6
   acts as a server for a client program that can read and set them.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 2 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
 
22
 
23
#include <stdio.h>
24
#include <sys/unistd.h>
25
#include <sys/types.h>
26
#include <sys/fcntl.h>
27
#include <sys/socket.h>
28
#include <arpa/inet.h>
29 53 nyawn
#include <netinet/in.h>
30
#include <unistd.h>
31 51 nyawn
#include <netdb.h>
32
#include <string.h>
33
#include <pthread.h>
34
#include <errno.h>
35
 
36
#include "spr-defs.h"
37
#include "dbg_api.h"
38
#include "hardware_monitor.h"
39
#include "errcodes.h"
40
 
41
 
42
#define debug(...) // fprintf(stderr, __VA_ARGS__ )
43
 
44
#define HWP_BUF_MAX 256
45
 
46
/*! Data structure for RSP buffers. Can't be null terminated, since it may
47
  include zero bytes */
48
struct rsp_buf
49
{
50
  char  data[HWP_BUF_MAX];
51
  int   len;
52
};
53
 
54
int hwp_server_fd = -1;
55
int hwp_client_fd = -1;
56
int hwp_pipe_fds[2];
57
 
58
/* Some convenient net address info to have around */
59
char hwp_ipstr[INET6_ADDRSTRLEN];
60
char *hwp_ipver;
61
int hwp_portnum;
62
char hwp_hostname[256];
63
 
64
/* Other local data */
65
int hwp_server_running = 0;
66
int hwp_target_is_running = 0;
67
int use_cached_dmr2 = 0;
68
uint32_t cached_dmr2 = 0;
69
 
70 56 nyawn
/* To track which watchpoints are in use by an external program,
71
 * so that the RSP server can have the unused ones for GDB
72
 */
73
#define HWP_MAX_WP 8
74
unsigned char hwp_in_use[HWP_MAX_WP];
75
 
76 51 nyawn
/*! String to map hex digits to chars */
77
static const char hexchars[]="0123456789abcdef";
78
 
79
pthread_t hwp_server_thread;
80
void *hwp_server(void *arg);
81
 
82
void hwp_server_close(void);
83
void hwp_client_close(void);
84
void hwp_client_request(void);
85
 
86
struct rsp_buf *hwp_get_packet(void);
87
void put_hwp_rsp_char(int fd, char c);
88
int get_hwp_rsp_char(int fd);
89
void hwp_read_reg(struct rsp_buf *buf);
90
void hwp_write_reg (struct rsp_buf *buf);
91
void hwp_put_str_packet (int fd, const char *str);
92
void hwp_put_packet (int fd, struct rsp_buf *buf);
93
unsigned long int hwp_hex2reg (char *buf);
94
void hwp_reg2hex (unsigned long int val, char *buf);
95
int hwp_hex(int c);
96
void hwp_report_run(void);
97
void hwp_report_stop(void);
98 56 nyawn
void hwp_set_in_use(unsigned int wp, unsigned char inuse);
99 51 nyawn
 
100
/*----------------------------------------------------------*/
101
/* Public API                                               */
102
/*----------------------------------------------------------*/
103
 
104 59 nyawn
int hwp_init(int portNum)
105 51 nyawn
{
106
  int status;
107
  struct addrinfo hints;
108
  struct addrinfo *servinfo;  // will point to the results of getaddrinfo
109
  int optval; /* Socket options */
110
  char portnum[6];  /* portNum as a string */
111
  void *addr;
112 56 nyawn
  int i, errcode;
113
  uint32_t regaddr, tmp;
114 51 nyawn
 
115
  debug("HWP Server initializing\n");
116
 
117 56 nyawn
  /* First thing's first:  Check if there are any HWP.
118
  * Read all DCR, mark which are present.*/
119
  status = 0;
120
  for(i = 0; i < HWP_MAX_WP; i++)
121
    {
122
      regaddr = SPR_DCR(i);
123
      errcode = dbg_cpu0_read(regaddr, &tmp);
124
      if(errcode != APP_ERR_NONE)
125
        {
126
          fprintf(stderr, "ERROR reading DCR %i at startup! %s\n", i,  get_err_string(errcode));
127
          hwp_set_in_use(i, 1);
128
        }
129
      else
130
        {
131
          if(tmp & 0x1)  /* HWP present */
132
            {
133
              hwp_set_in_use(i, 0);
134
              status++;
135
            }
136
          else  /* HWP not implemented */
137
            {
138
              hwp_set_in_use(i, 1);
139
            }
140
        }
141
      debug("HWP %i is %s\n", i, hwp_in_use[i] ? "absent":"present");
142
    }
143
 
144 59 nyawn
  if(status <= 0)
145 56 nyawn
    {
146 59 nyawn
      fprintf(stderr, "No watchpoint hardware found, HWP server not starting\n");
147
      return 0;
148 56 nyawn
    }
149
  else
150
    {
151 59 nyawn
      fprintf(stderr, "HWP server initializing with %i watchpoints available\n", status);
152 56 nyawn
 
153 59 nyawn
      /* We have watchpoint hardware.  Initialize the server. */
154
      hwp_server_fd      = -1;
155
      hwp_client_fd      = -1;
156
      hwp_portnum = portNum;
157
 
158
      memset(portnum, '\0', sizeof(portnum));
159
      snprintf(portnum, 5, "%i", portNum);
160
 
161
      /* Get the address info for the local host */
162
      memset(&hints, 0, sizeof hints); // make sure the struct is empty
163
      hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
164
      hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
165
      hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
166
 
167
      if ((status = getaddrinfo(NULL, portnum, &hints, &servinfo)) != 0) {
168
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
169
        return 0;
170
      }
171
 
172
 
173
      /* *** TODO: Select the appropriate servinfo in the linked list
174
       * For now, we just use the first entry in servinfo.
175
       struct addrinfo *servinfo, *p;
176
       for(p = servinfo;p != NULL; p = p->ai_next) {
177
       if (p->ai_family == AF_INET) { // IPv4
178
       } else { // IPv6
179
       }
180
       }
181
      */
182
 
183
 
184
      /* Save the IP address, for convenience (different fields in IPv4 and IPv6) */
185
      if (servinfo->ai_family == AF_INET) { // IPv4
186
        struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr;
187
        addr = &(ipv4->sin_addr);
188
        hwp_ipver = "IPv4";
189
      } else { // IPv6
190
        struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr;
191
        addr = &(ipv6->sin6_addr);
192
        hwp_ipver = "IPv6";
193
      }
194
 
195
      /* convert the IP to a string */
196
      inet_ntop(servinfo->ai_family, addr, hwp_ipstr, sizeof(hwp_ipstr));
197
 
198
      /* Find out what our name is, save for convenience */
199
      if (gethostname (hwp_hostname, sizeof(hwp_hostname)) < 0)
200
        {
201
          fprintf (stderr, "Warning: Unable to get hostname for HWP server: %s\n", strerror(errno));
202
          hwp_hostname[0] = '\0';  /* This is not a fatal error. */
203
        }
204
 
205
      /* Create the socket */
206
      hwp_server_fd = socket (servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
207
      if (hwp_server_fd < 0)
208
        {
209
          fprintf (stderr, "Error: HWP could not create server socket: %s\n", strerror(errno));
210
          return 0;
211
        }
212
 
213
      /* Set this socket to reuse its address. */
214
      optval = 1;
215
      if (setsockopt(hwp_server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) == -1)
216
        {
217
          fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: %s\n", hwp_server_fd, strerror(errno));
218
          hwp_server_close();
219
          return 0;
220
        }
221
 
222
      /* Bind the socket to the local address */
223
      if (bind (hwp_server_fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0)
224
        {
225
          fprintf (stderr, "Error: Unable to bind HWP server socket %d to port %d: %s\n", hwp_server_fd, portNum, strerror(errno));
226
          hwp_server_close();
227
          return 0;
228
        }
229
 
230
      /* Set us up as a server, with a maximum backlog of 1 connection */
231
      if (listen (hwp_server_fd, 1) < 0)
232
        {
233
          fprintf (stderr, "Warning: Unable to set HWP backlog on server socket %d to %d: %s\n", hwp_server_fd, 1, strerror(errno));
234
          hwp_server_close();
235
          return 0;
236
        }
237
 
238
      fprintf(stderr, "HWP server listening on host %s (%s), port %i, address family %s\n",
239
              hwp_hostname, hwp_ipstr, hwp_portnum, hwp_ipver);
240
 
241
      /* Register for stall/unstall events from the target monitor thread. Also creates pipe
242
       * for sending stall/unstall command to the target monitor, unused by us. */
243
      if(0 > register_with_monitor_thread(hwp_pipe_fds)) {  // pipe_fds[0] is for writing to monitor, [1] is to read from it
244
        fprintf(stderr, "HWP server failed to register with monitor thread, exiting");
245
        hwp_server_close();
246
        return 0;
247
      }
248 51 nyawn
    }
249
 
250 59 nyawn
  return 1;
251 51 nyawn
}
252
 
253
 
254
int hwp_server_start(void)
255
{
256
 
257
  hwp_server_running = 1;
258
 
259
  debug("Starting HWP server\n");
260
 
261
  // Create the HWP server thread
262
  if(pthread_create(&hwp_server_thread, NULL, hwp_server, NULL))
263
    {
264
      fprintf(stderr, "Failed to create HWP server thread!\n");
265
      return 0;
266
    }
267
 
268
  return 1;
269
}
270
 
271
 
272
int hwp_server_stop(void)
273
{
274
  /*** NOTE: Since we currently don't use select() in front of the accept()
275
   *** in the server thread, this won't actually work unless/until a client
276
   *** is connected.  Otherwise, the server thread will be blocked on the
277
   *** accept() (though closing the server socket may break it out.)
278
   ***/
279
 
280
  hwp_server_running = 0;
281
  hwp_server_close();
282
  return 1;
283
}
284
 
285
/*--------------------------------------------------------------------*/
286
/* Main server thread                                                 */
287
/*--------------------------------------------------------------------*/
288
 
289
 
290
void *hwp_server(void *arg)
291
{
292
  struct sockaddr_storage their_addr;
293
  struct timeval *tvp;
294
  fd_set  readset;
295
  socklen_t addr_size;
296
  int nfds, flags;
297
  int ret;
298
  char cmd;
299
 
300
  fprintf(stderr, "HWP server thread running!\n");
301
 
302
  while(hwp_server_running)
303
    {
304
      /* Listen for an incoming connection */
305
      addr_size = sizeof their_addr;
306
      hwp_client_fd = accept(hwp_server_fd, (struct sockaddr *)&their_addr, &addr_size);
307
 
308
      if(hwp_client_fd == -1)
309
        {
310
          perror("Error in accept() in HWP server thread");
311
        }
312
      else
313
        {
314
          debug("HWP server got connection!\n");
315
 
316
          /* Do new client init stuff here */
317
          use_cached_dmr2 = 0;
318
 
319
          /* New client should be non-blocking. */
320
          flags = fcntl (hwp_client_fd, F_GETFL);
321
          if (flags < 0)
322
            {
323
              fprintf (stderr, "Warning: Unable to get flags for HWP client socket %d: %s\n", hwp_client_fd, strerror(errno));
324
              // Not really fatal.
325
            }
326
          else {
327
            flags |= O_NONBLOCK;
328
            if (fcntl (hwp_client_fd, F_SETFL, flags) < 0)
329
              {
330
                fprintf (stderr, "Warning: Unable to set flags for HWP client socket %d to 0x%08x: %s\n", hwp_client_fd, flags, strerror(errno));
331
                // Also not really fatal.
332
              }
333
          }
334
        }
335
 
336
      /* Send/receive data on the new connection for as long as it's valid */
337
      while(hwp_server_running && (hwp_client_fd != -1))
338
        {
339
          /* if target not running, block on data from client or monitor thread */
340
          /* if target running, just poll (don't block) */
341
          // if(hwp_target_is_running) {
342
          //  tv.tv_sec = 0;  // Set this each loop, it may be changed by the select() call
343
          //  tv.tv_usec = 0;  // instant timeout when polling
344
          //  tvp = &tv;
345
          //} else {
346
            tvp = NULL;
347
            //}
348
 
349
          FD_ZERO(&readset);
350
          FD_SET(hwp_client_fd, &readset);
351
          FD_SET(hwp_pipe_fds[1], &readset);
352
          nfds = hwp_client_fd;
353
          if(hwp_pipe_fds[1] > nfds) nfds = hwp_pipe_fds[1];
354
          nfds++;
355
 
356
          ret = select(nfds, &readset, NULL, NULL, tvp);
357
 
358
          if(ret == -1)  // error
359
            {
360
                perror("select()");
361
            }
362
          else if(ret != 0)  // fd ready (ret == 0 on timeout)
363
            {
364
              debug("HWP thread got data\n");
365
 
366
              if(FD_ISSET(hwp_pipe_fds[1], &readset))
367
                {
368
                  ret = read(hwp_pipe_fds[1], &cmd, 1);
369
                  debug("HWP server got monitor status \'%c\' (0x%X)\n", cmd, cmd);
370
                  if(ret == 1)
371
                    {
372
                      if(cmd == 'H')
373
                        {
374
                          // Save state so we can tell client on request
375
                          hwp_target_is_running = 0;
376
                        }
377
                      else if(cmd == 'R')
378
                        {
379
                          // Save state so we can tell client on request
380
                          hwp_target_is_running = 1;
381
                          use_cached_dmr2 = 0;
382
                        }
383
                      else
384
                        {
385
                          fprintf(stderr, "HWP server got unknown monitor status \'%c\' (0x%X)\n", cmd, cmd);
386
                        }
387
                    }
388
                  else
389
                    {
390
                      fprintf(stderr, "HWP server failed to read from ready monitor pipe!\n");
391
                    }
392
                }  // if FD_ISSET(hwp_pipe_fds[1])
393
 
394
              if(FD_ISSET(hwp_client_fd, &readset))
395
                {
396
                  hwp_client_request();
397
                }
398
            }   // else if (ret != 0)
399
 
400
        }  /* while client connection is valid */
401
 
402
    } /* while(hwp_server_running) */
403
 
404
  hwp_client_close();
405
 
406
  return arg;  // unused
407
}
408
 
409
/*--------------------------------------------------------------------*/
410
/* Helper functions                                                   */
411
/*--------------------------------------------------------------------*/
412
 
413
void hwp_server_close(void)
414
{
415
  if (hwp_server_fd != -1)
416
    {
417
      close(hwp_server_fd);
418
      hwp_server_fd = -1;
419
    }
420
}
421
 
422
 
423
void hwp_client_close(void)
424
{
425
  if (hwp_client_fd != -1)
426
    {
427
      close (hwp_client_fd);
428
      hwp_client_fd = -1;
429
    }
430
}       /* hwp_client_close () */
431
 
432
 
433
void hwp_client_request(void)
434
{
435
  struct rsp_buf *buf = hwp_get_packet ();      /* Message sent to us */
436
 
437
  // Null packet means we hit EOF or the link was closed for some other
438
  // reason. Close the client and return
439
  if (NULL == buf)
440
    {
441
      hwp_client_close ();
442
      return;
443
    }
444
 
445
  debug("HWP Packet received %s: %d chars\n", buf->data, buf->len );
446
 
447
  switch (buf->data[0])
448
    {
449
 
450
    case '?':
451
      // Different meaning than RSP: in RSP, this always returns an 'S' packet.
452
      // here, we want to know running / stopped.
453
      if(hwp_target_is_running) {
454
        hwp_report_run();
455
      } else {
456
        hwp_report_stop();
457
      }
458
      return;
459
 
460
 
461
      /*
462
        case 'g':
463
        rsp_read_all_regs ();
464
        return;
465
 
466
        case 'G':
467
        rsp_write_all_regs (buf);
468
        return;
469
      */
470
 
471
 
472
    case 'p':
473
      /* Read a register */
474
      hwp_read_reg(buf);
475
      return;
476
 
477
    case 'P':
478
      /* Write a register */
479
      hwp_write_reg(buf);
480
      return;
481
 
482
      /*
483
        case 'q':
484
        // Any one of a number of query packets
485
        rsp_query (buf);
486
        return;
487
 
488
        case 'Q':
489
        // Any one of a number of set packets
490
        rsp_set (buf);
491
        return;
492
      */
493
 
494
    default:
495
      /* Unknown commands are ignored */
496
      fprintf (stderr, "Warning: Unknown HWP request %s\n", buf->data);
497
      return;
498
    }
499
}       /* hwp_client_request () */
500
 
501
 
502
/*---------------------------------------------------------------------------*/
503
/*!Get a packet from the GDB client
504
 
505
   Modeled on the stub version supplied with GDB. The data is in a static
506
   buffer. The data should be copied elsewhere if it is to be preserved across
507
   a subsequent call to get_packet().
508
 
509
   Unlike the reference implementation, we don't deal with sequence
510
   numbers. GDB has never used them, and this implementation is only intended
511
   for use with GDB 6.8 or later. Sequence numbers were removed from the RSP
512
   standard at GDB 5.0.
513
 
514
   @return  A pointer to the static buffer containing the data                */
515
/*---------------------------------------------------------------------------*/
516
struct rsp_buf *hwp_get_packet(void)
517
{
518
  static struct rsp_buf  buf;           /* Survives the return */
519
 
520
  /* Keep getting packets, until one is found with a valid checksum */
521
  while (1)
522
    {
523
      unsigned char  checksum;          /* The checksum we have computed */
524
      int            count;             /* Index into the buffer */
525
      int            ch;                /* Current character */
526
 
527
      /* Wait around for the start character ('$'). Ignore all other
528
         characters */
529
      ch = get_hwp_rsp_char(hwp_client_fd);
530
      while (ch != '$')
531
        {
532
          if (-1 == ch)
533
            {
534
              return  NULL;             /* Connection failed */
535
            }
536
 
537
          ch = get_hwp_rsp_char(hwp_client_fd);
538
        }
539
 
540
      /* Read until a '#' or end of buffer is found */
541
      checksum =  0;
542
      count    =  0;
543
      while (count < HWP_BUF_MAX - 1)
544
        {
545
          ch = get_hwp_rsp_char(hwp_client_fd);
546
 
547
          /* Check for connection failure */
548
          if (-1 == ch)
549
            {
550
              return  NULL;
551
            }
552
 
553
          /* If we hit a start of line char begin all over again */
554
          if ('$' == ch)
555
            {
556
              checksum =  0;
557
              count    =  0;
558
 
559
              continue;
560
            }
561
 
562
          /* Break out if we get the end of line char */
563
          if ('#' == ch)
564
            {
565
              break;
566
            }
567
 
568
          /* Update the checksum and add the char to the buffer */
569
 
570
          checksum        = checksum + (unsigned char)ch;
571
          buf.data[count] = (char)ch;
572
          count           = count + 1;
573
        }
574
 
575
      /* Mark the end of the buffer with EOS - it's convenient for non-binary
576
         data to be valid strings. */
577
      buf.data[count] = 0;
578
      buf.len         = count;
579
 
580
      /* If we have a valid end of packet char, validate the checksum */
581
      if ('#' == ch)
582
        {
583
          unsigned char  xmitcsum;      /* The checksum in the packet */
584
 
585
          ch = get_hwp_rsp_char(hwp_client_fd);
586
          if (-1 == ch)
587
            {
588
              return  NULL;             /* Connection failed */
589
            }
590
          xmitcsum = hwp_hex(ch) << 4;
591
 
592
          ch = get_hwp_rsp_char(hwp_client_fd);
593
          if (-1 == ch)
594
            {
595
              return  NULL;             /* Connection failed */
596
            }
597
 
598
          xmitcsum += hwp_hex(ch);
599
 
600
          /* If the checksums don't match print a warning, and put the
601
             negative ack back to the client. Otherwise put a positive ack. */
602
          if (checksum != xmitcsum)
603
            {
604
              fprintf (stderr, "Warning: Bad HWP RSP checksum: Computed "
605
                       "0x%02x, received 0x%02x\n", checksum, xmitcsum);
606
 
607
              put_hwp_rsp_char (hwp_client_fd, '-');    /* Failed checksum */
608
            }
609
          else
610
            {
611
              put_hwp_rsp_char (hwp_client_fd, '+');    /* successful transfer */
612
              break;
613
            }
614
        }
615
      else
616
        {
617
          fprintf (stderr, "Warning: HWP RSP packet overran buffer\n");
618
        }
619
    }
620
 
621
  return &buf;                          /* Success */
622
 
623
}       /* hwp_get_packet () */
624
 
625
 
626
/*---------------------------------------------------------------------------*/
627
/*Single character get/set routines                                          */
628
/*---------------------------------------------------------------------------*/
629
void put_hwp_rsp_char(int fd, char  c)
630
{
631
  if (-1 == fd)
632
    {
633
      fprintf (stderr, "Warning: Attempt to write '%c' to unopened HWP RSP client: Ignored\n", c);
634
      return;
635
    }
636
 
637
  /* Write until successful (we retry after interrupts) or catastrophic
638
     failure. */
639
  while (1)
640
    {
641
      switch (write(fd, &c, sizeof (c)))
642
        {
643
        case -1:
644
          /* Error: only allow interrupts or would block */
645
          if ((EAGAIN != errno) && (EINTR != errno))
646
            {
647
              fprintf (stderr, "Warning: Failed to write to HWP RSP client: Closing client connection: %s\n",
648
                       strerror (errno));
649
              hwp_client_close();
650
              return;
651
            }
652
 
653
          break;
654
 
655
        case 0:
656
          break;                /* Nothing written! Try again */
657
 
658
        default:
659
          return;               /* Success, we can return */
660
        }
661
    }
662
}       /* put_hwp_rsp_char() */
663
 
664
 
665
 
666
int get_hwp_rsp_char(int fd)
667
{
668
  unsigned char  c;             /* The character read */
669
 
670
  if (-1 == fd)
671
    {
672
      fprintf (stderr, "Warning: Attempt to read from unopened HWP RSP client: Ignored\n");
673
      return  -1;
674
    }
675
 
676
  /* Read until successful (we retry after interrupts) or catastrophic
677
     failure. */
678
  while (1)
679
    {
680
      switch (read (fd, &c, sizeof (c)))
681
        {
682
        case -1:
683
          /* Error: only allow interrupts or would block */
684
          if ((EAGAIN != errno) && (EINTR != errno))
685
            {
686
              fprintf (stderr, "Warning: Failed to read from HWP RSP client: Closing client connection: %s\n",
687
                       strerror (errno));
688
              hwp_client_close();
689
              return  -1;
690
            }
691
 
692
          break;
693
 
694
        case 0:
695
          // EOF
696
          hwp_client_close();
697
          return  -1;
698
 
699
        default:
700
          return  c & 0xff;     /* Success, we can return (no sign extend!) */
701
        }
702
    }
703
}       /* get_hwp_rsp_char() */
704
 
705
 
706
/*---------------------------------------------------------------------------*/
707
/*!Read a single register
708
 
709
   The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
710
   (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a
711
   sequence of bytes in target endian order.
712
 
713
   Each byte is packed as a pair of hex digits.
714
 
715
   @param[in] buf  The original packet request. Reused for the reply.        */
716
/*---------------------------------------------------------------------------*/
717
void hwp_read_reg(struct rsp_buf *buf)
718
{
719
  unsigned int  regnum;
720
  uint32_t tmp;
721
  unsigned int errcode = APP_ERR_NONE;
722
 
723
  /* Break out the fields from the data */
724
  if (1 != sscanf (buf->data, "p%x", &regnum))
725
    {
726
      fprintf (stderr, "Warning: Failed to recognize HWP RSP read register command: \'%s\'\n", buf->data);
727
      hwp_put_str_packet (hwp_client_fd, "E01");
728
      return;
729
    }
730
 
731
  if((regnum == SPR_DMR2) && use_cached_dmr2)  // Should we use the cached DMR2 value?
732
    {
733
      tmp = cached_dmr2;
734
      errcode = APP_ERR_NONE;
735
      fprintf(stderr, "Using cached DMR2 value 0x%X\n", tmp);
736
    }
737
  else
738
    {
739
      /* Get the relevant register.  We assume the client is not GDB,
740
       * and that no register number translation is needed.
741
       */
742
      errcode = dbg_cpu0_read(regnum, &tmp);
743
    }
744
 
745
  if(errcode == APP_ERR_NONE) {
746
    hwp_reg2hex(tmp, buf->data);
747
    buf->len = strlen (buf->data);
748
    debug("Read reg 0x%x, got %s (0x%X), len %i\n", regnum, buf->data, tmp, buf->len);
749
    hwp_put_packet (hwp_client_fd, buf);
750
  }
751
  else {
752
    fprintf(stderr, "Error reading HWP register: %s\n", get_err_string(errcode));
753
    hwp_put_str_packet(hwp_client_fd, "E01");
754
  }
755
 
756
}       /* hwp_read_reg() */
757
 
758
 
759
/*---------------------------------------------------------------------------*/
760
/*!Write a single register
761
 
762
   The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
763
   (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a
764
   sequence of bytes in target endian order.
765
 
766
   Each byte is packed as a pair of hex digits.
767
 
768
   @param[in] buf  The original packet request.                              */
769
/*---------------------------------------------------------------------------*/
770
void hwp_write_reg (struct rsp_buf *buf)
771
{
772
  unsigned int  regnum;
773
  char          valstr[9];              /* Allow for EOS on the string */
774
  unsigned int  errcode = APP_ERR_NONE;
775 56 nyawn
  int dcridx;
776
  uint32_t val, cc, ct;
777 51 nyawn
 
778
  /* Break out the fields from the data */
779
  if (2 != sscanf (buf->data, "P%x=%8s", &regnum, valstr))
780
    {
781
      fprintf (stderr, "Warning: Failed to recognize RSP write register command: %s\n", buf->data);
782
      hwp_put_str_packet (hwp_client_fd, "E01");
783
      return;
784
    }
785
 
786
  /* Set the relevant register.  We assume that the client is not
787
   * GDB, and no register number translation is needed. */
788 56 nyawn
  val =  hwp_hex2reg(valstr);
789
  errcode = dbg_cpu0_write(regnum, val);
790 51 nyawn
 
791
  if(errcode == APP_ERR_NONE) {
792
    debug("Wrote reg 0x%X with val 0x%X (%s)\n", regnum, hwp_hex2reg(valstr), valstr);
793
    hwp_put_str_packet (hwp_client_fd, "OK");
794
  }
795
  else {
796
    fprintf(stderr, "Error writing register: %s\n", get_err_string(errcode));
797
    hwp_put_str_packet(hwp_client_fd, "E01");
798
  }
799
 
800 56 nyawn
  /* A bit of hackery: Determine if this write enables a comparison on a DCR.
801
   * If so, then we mark this HWP as in use, so that GDB/RSP cannot use it.
802
   * Note that there's no point making the HWP client check which watchpoints are in
803
   * use - GDB only sets HWP as it is starting the CPU, and clears them
804
   * immediately after a stop.  So as far as the HWP client would see, GDB/RSP
805
   * never uses any watchpoints.
806
   */
807
 
808
  if((regnum >= SPR_DCR(0)) && (regnum <= SPR_DCR(7)))
809
    {
810
      dcridx = regnum - SPR_DCR(0);
811
      /* If the 'compare condition' (cc) or 'compare to' (ct) are 0,
812
       * then matching is disabled and we can mark this HWP not in use.
813
       */
814
      cc = val & 0x0E;
815
      ct = val & 0xE0;
816
      if ((cc == 0) || (ct == 0))
817
        hwp_set_in_use(dcridx, 0);
818
      else
819
        hwp_set_in_use(dcridx, 1);
820
    }
821
 
822 51 nyawn
}       /* hwp_write_reg() */
823
 
824
/*---------------------------------------------------------------------------*/
825
/*!Convenience to put a constant string packet
826
 
827
   param[in] str  The text of the packet                                     */
828
/*---------------------------------------------------------------------------*/
829
void hwp_put_str_packet (int fd, const char *str)
830
{
831
  struct rsp_buf  buf;
832
  int             len = strlen (str);
833
 
834
  /* Construct the packet to send, so long as string is not too big,
835
     otherwise truncate. Add EOS at the end for convenient debug printout */
836
 
837
  if (len >= HWP_BUF_MAX)
838
    {
839
      fprintf (stderr, "Warning: String %s too large for HWP RSP packet: truncated\n", str);
840
      len = HWP_BUF_MAX - 1;
841
    }
842
 
843
  strncpy (buf.data, str, len);
844
  buf.data[len] = 0;
845
  buf.len       = len;
846
 
847
  hwp_put_packet (fd, &buf);
848
 
849
}       /* hwp_put_str_packet () */
850
 
851
/*---------------------------------------------------------------------------*/
852
/*!Send a packet to the GDB client
853
 
854
   Modeled on the stub version supplied with GDB. Put out the data preceded by
855
   a '$', followed by a '#' and a one byte checksum. '$', '#', '*' and '}' are
856
   escaped by preceding them with '}' and then XORing the character with
857
   0x20.
858
 
859
   @param[in] buf  The data to send                                          */
860
/*---------------------------------------------------------------------------*/
861
void hwp_put_packet (int fd, struct rsp_buf *buf)
862
{
863
  int  ch;                              /* Ack char */
864
 
865
  /* Construct $<packet info>#<checksum>. Repeat until the GDB client
866
     acknowledges satisfactory receipt. */
867
  do
868
    {
869
      unsigned char checksum = 0;        /* Computed checksum */
870
      int           count    = 0;        /* Index into the buffer */
871
 
872
      debug("Putting %s\n", buf->data);
873
 
874
      put_hwp_rsp_char (fd, '$');               /* Start char */
875
 
876
      /* Body of the packet */
877
      for (count = 0; count < buf->len; count++)
878
        {
879
          unsigned char  ch = buf->data[count];
880
 
881
          /* Check for escaped chars */
882
          if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch))
883
            {
884
              ch       ^= 0x20;
885
              checksum += (unsigned char)'}';
886
              put_hwp_rsp_char (fd, '}');
887
            }
888
 
889
          checksum += ch;
890
          put_hwp_rsp_char (fd, ch);
891
        }
892
 
893
      put_hwp_rsp_char (fd, '#');               /* End char */
894
 
895
      /* Computed checksum */
896
      put_hwp_rsp_char (fd, hexchars[checksum >> 4]);
897
      put_hwp_rsp_char (fd, hexchars[checksum % 16]);
898
 
899
      /* Check for ack or connection failure */
900
      ch = get_hwp_rsp_char (fd);
901
      if (-1 == ch)
902
        {
903
          return;                       /* Fail the put silently. */
904
        }
905
    }
906
  while ('+' != ch);
907
 
908
}       /* hwp_put_packet() */
909
 
910
 
911
unsigned long int hwp_hex2reg (char *buf)
912
{
913
  int                n;         /* Counter for digits */
914
  unsigned long int  val = 0;    /* The result */
915
 
916
  for (n = 0; n < 8; n++)
917
    {
918
#ifdef WORDSBIGENDIAN
919
      int  nyb_shift = n * 4;
920
#else
921
      int  nyb_shift = 28 - (n * 4);
922
#endif
923
      val |= hwp_hex(buf[n]) << nyb_shift;
924
    }
925
 
926
  return val;
927
 
928
}       /* hwp_hex2reg() */
929
 
930
 
931
void hwp_reg2hex(unsigned long int val, char *buf)
932
{
933
  int  n;                       /* Counter for digits */
934
 
935
  for (n = 0; n < 8; n++)
936
    {
937
#ifdef WORDSBIGENDIAN
938
      int  nyb_shift = n * 4;
939
#else
940
      int  nyb_shift = 28 - (n * 4);
941
#endif
942
      buf[n] = hexchars[(val >> nyb_shift) & 0xf];
943
    }
944
 
945
  buf[8] = 0;                    /* Useful to terminate as string */
946
 
947
}       /* hwp_reg2hex() */
948
 
949
 
950
int hwp_hex(int c)
951
{
952
  return  ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 :
953
          ((c >= '0') && (c <= '9')) ? c - '0' :
954
          ((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1;
955
 
956
}       /* hwp_hex() */
957
 
958
/* ---------------------------------------------------------------------- */
959
/* Functions to report stop and start to the client.                      */
960
/* Not strictly correct RSP protocol.                                     */
961
/*------------------------------------------------------------------------*/
962
 
963
void hwp_report_stop(void)
964
{
965
  struct rsp_buf  buf;
966
  uint32_t ppcval;
967
 
968
  // Read the PPC
969
  dbg_cpu0_read(SPR_PPC, &ppcval);
970
 
971
  debug("HWP reporting stop, PPC = 0x%X\n", ppcval);
972
 
973
  /* Construct a signal received packet */
974
  buf.data[0] = 'S';
975
  buf.data[1] = hexchars[ppcval >> 4];
976
  buf.data[2] = hexchars[ppcval % 16];
977
  buf.data[3] = 0;
978
  buf.len     = strlen (buf.data);
979
 
980
  hwp_put_packet(hwp_client_fd, &buf);
981
 
982
}       /* rsp_report_exception () */
983
 
984
 
985
void hwp_report_run(void)
986
{
987
  struct rsp_buf  buf;
988
 
989
  // Construct a 'run' packet.  This is completely non-standard, non-RSP, made up.
990
  buf.data[0] = 'R';
991
  buf.data[1] = 'U';
992
  buf.data[2] = 'N';
993
  buf.data[3] = 0;
994
  buf.len     = strlen (buf.data);
995
 
996
  hwp_put_packet(hwp_client_fd, &buf);
997
 
998
}  /* hwp_report_run() */
999
 
1000 56 nyawn
/* Used by the HWP server to indicate which HWP are
1001
 * in long-term use by an external client
1002
 */
1003
void hwp_set_in_use(unsigned int wp, unsigned char inuse)
1004
{
1005
  if(wp < HWP_MAX_WP)
1006
    {
1007
      hwp_in_use[wp] = inuse;
1008
      debug("HWP setting wp %i status to %i\n", wp, inuse);
1009
    }
1010
  else
1011
    fprintf(stderr, "ERROR! value %i out of range when setting HWP in use!\n", wp);
1012
}
1013
 
1014
/* Called by the RSP server to get any one unused HWP.
1015
 * This will only be called immediately before a 'step'
1016
 * or 'continue,' and the HWP will be disabled as soon
1017
 * as the CPU returns control to the RSP server.
1018
 * Returns -1 if no HWP available.
1019
 */
1020
int hwp_get_available_watchpoint(void)
1021
{
1022
  int i;
1023
  int ret = -1;
1024
 
1025
  for(i = 0; i < HWP_MAX_WP; i++)
1026
    {
1027
      if(hwp_in_use[i] == 0)
1028
        {
1029
          ret = i;
1030
          hwp_in_use[i] = 1;
1031
 
1032
          break;
1033
        }
1034
    }
1035
  debug("HWP granting wp %i to GDB/RSP\n", ret);
1036
  return ret;
1037
}
1038
 
1039
/* Called by the RSP server to indicate it is no longer
1040
 * using a watchpoint previously granted by
1041
 * hwp_get_available_watchpoint()
1042
 */
1043
void hwp_return_watchpoint(int wp)
1044
{
1045
  if(wp >= HWP_MAX_WP)
1046
    {
1047
      fprintf(stderr, "ERROR! WP value %i out of range in hwp_return_watchpoint()!\n", wp);
1048
    }
1049
  else
1050
    {
1051
      if(hwp_in_use[wp] != 0)
1052
        {
1053
          hwp_in_use[wp] = 0;
1054
          debug("HWP got wp %i back from GDB/RSP\n", wp);
1055
        }
1056
      else
1057
        fprintf(stderr, "ERROR! hwp_return_watchpoint() returning wp %i, not in use!\n", wp);
1058
    }
1059
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.