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 56

Go to most recent revision | 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
void hwp_init(int portNum)
105
{
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
  if(status > 0)
145
    {
146
      fprintf(stderr, "HWP server initializing with %i watchpoints available\n", status);
147
    }
148
  else
149
    {
150
      fprintf(stderr, "No watchpoint hardware found, HWP server not starting\n");
151
    }
152
 
153
  /* We have watchpoint hardware.  Initialize the server. */
154 51 nyawn
  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;
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;
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;
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;
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;
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;
247
  }
248
 
249
}
250
 
251
 
252
int hwp_server_start(void)
253
{
254
 
255
  hwp_server_running = 1;
256
 
257
  debug("Starting HWP server\n");
258
 
259
  // Create the HWP server thread
260
  if(pthread_create(&hwp_server_thread, NULL, hwp_server, NULL))
261
    {
262
      fprintf(stderr, "Failed to create HWP server thread!\n");
263
      return 0;
264
    }
265
 
266
  return 1;
267
}
268
 
269
 
270
int hwp_server_stop(void)
271
{
272
  /*** NOTE: Since we currently don't use select() in front of the accept()
273
   *** in the server thread, this won't actually work unless/until a client
274
   *** is connected.  Otherwise, the server thread will be blocked on the
275
   *** accept() (though closing the server socket may break it out.)
276
   ***/
277
 
278
  hwp_server_running = 0;
279
  hwp_server_close();
280
  return 1;
281
}
282
 
283
/*--------------------------------------------------------------------*/
284
/* Main server thread                                                 */
285
/*--------------------------------------------------------------------*/
286
 
287
 
288
void *hwp_server(void *arg)
289
{
290
  struct sockaddr_storage their_addr;
291
  struct timeval *tvp;
292
  fd_set  readset;
293
  socklen_t addr_size;
294
  int nfds, flags;
295
  int ret;
296
  char cmd;
297
 
298
  fprintf(stderr, "HWP server thread running!\n");
299
 
300
  while(hwp_server_running)
301
    {
302
      /* Listen for an incoming connection */
303
      addr_size = sizeof their_addr;
304
      hwp_client_fd = accept(hwp_server_fd, (struct sockaddr *)&their_addr, &addr_size);
305
 
306
      if(hwp_client_fd == -1)
307
        {
308
          perror("Error in accept() in HWP server thread");
309
        }
310
      else
311
        {
312
          debug("HWP server got connection!\n");
313
 
314
          /* Do new client init stuff here */
315
          use_cached_dmr2 = 0;
316
 
317
          /* New client should be non-blocking. */
318
          flags = fcntl (hwp_client_fd, F_GETFL);
319
          if (flags < 0)
320
            {
321
              fprintf (stderr, "Warning: Unable to get flags for HWP client socket %d: %s\n", hwp_client_fd, strerror(errno));
322
              // Not really fatal.
323
            }
324
          else {
325
            flags |= O_NONBLOCK;
326
            if (fcntl (hwp_client_fd, F_SETFL, flags) < 0)
327
              {
328
                fprintf (stderr, "Warning: Unable to set flags for HWP client socket %d to 0x%08x: %s\n", hwp_client_fd, flags, strerror(errno));
329
                // Also not really fatal.
330
              }
331
          }
332
        }
333
 
334
      /* Send/receive data on the new connection for as long as it's valid */
335
      while(hwp_server_running && (hwp_client_fd != -1))
336
        {
337
          /* if target not running, block on data from client or monitor thread */
338
          /* if target running, just poll (don't block) */
339
          // if(hwp_target_is_running) {
340
          //  tv.tv_sec = 0;  // Set this each loop, it may be changed by the select() call
341
          //  tv.tv_usec = 0;  // instant timeout when polling
342
          //  tvp = &tv;
343
          //} else {
344
            tvp = NULL;
345
            //}
346
 
347
          FD_ZERO(&readset);
348
          FD_SET(hwp_client_fd, &readset);
349
          FD_SET(hwp_pipe_fds[1], &readset);
350
          nfds = hwp_client_fd;
351
          if(hwp_pipe_fds[1] > nfds) nfds = hwp_pipe_fds[1];
352
          nfds++;
353
 
354
          ret = select(nfds, &readset, NULL, NULL, tvp);
355
 
356
          if(ret == -1)  // error
357
            {
358
                perror("select()");
359
            }
360
          else if(ret != 0)  // fd ready (ret == 0 on timeout)
361
            {
362
              debug("HWP thread got data\n");
363
 
364
              if(FD_ISSET(hwp_pipe_fds[1], &readset))
365
                {
366
                  ret = read(hwp_pipe_fds[1], &cmd, 1);
367
                  debug("HWP server got monitor status \'%c\' (0x%X)\n", cmd, cmd);
368
                  if(ret == 1)
369
                    {
370
                      if(cmd == 'H')
371
                        {
372
                          // Save state so we can tell client on request
373
                          hwp_target_is_running = 0;
374
                        }
375
                      else if(cmd == 'R')
376
                        {
377
                          // Save state so we can tell client on request
378
                          hwp_target_is_running = 1;
379
                          use_cached_dmr2 = 0;
380
                        }
381
                      else
382
                        {
383
                          fprintf(stderr, "HWP server got unknown monitor status \'%c\' (0x%X)\n", cmd, cmd);
384
                        }
385
                    }
386
                  else
387
                    {
388
                      fprintf(stderr, "HWP server failed to read from ready monitor pipe!\n");
389
                    }
390
                }  // if FD_ISSET(hwp_pipe_fds[1])
391
 
392
              if(FD_ISSET(hwp_client_fd, &readset))
393
                {
394
                  hwp_client_request();
395
                }
396
            }   // else if (ret != 0)
397
 
398
        }  /* while client connection is valid */
399
 
400
    } /* while(hwp_server_running) */
401
 
402
  hwp_client_close();
403
 
404
  return arg;  // unused
405
}
406
 
407
/*--------------------------------------------------------------------*/
408
/* Helper functions                                                   */
409
/*--------------------------------------------------------------------*/
410
 
411
void hwp_server_close(void)
412
{
413
  if (hwp_server_fd != -1)
414
    {
415
      close(hwp_server_fd);
416
      hwp_server_fd = -1;
417
    }
418
}
419
 
420
 
421
void hwp_client_close(void)
422
{
423
  if (hwp_client_fd != -1)
424
    {
425
      close (hwp_client_fd);
426
      hwp_client_fd = -1;
427
    }
428
}       /* hwp_client_close () */
429
 
430
 
431
void hwp_client_request(void)
432
{
433
  struct rsp_buf *buf = hwp_get_packet ();      /* Message sent to us */
434
 
435
  // Null packet means we hit EOF or the link was closed for some other
436
  // reason. Close the client and return
437
  if (NULL == buf)
438
    {
439
      hwp_client_close ();
440
      return;
441
    }
442
 
443
  debug("HWP Packet received %s: %d chars\n", buf->data, buf->len );
444
 
445
  switch (buf->data[0])
446
    {
447
 
448
    case '?':
449
      // Different meaning than RSP: in RSP, this always returns an 'S' packet.
450
      // here, we want to know running / stopped.
451
      if(hwp_target_is_running) {
452
        hwp_report_run();
453
      } else {
454
        hwp_report_stop();
455
      }
456
      return;
457
 
458
 
459
      /*
460
        case 'g':
461
        rsp_read_all_regs ();
462
        return;
463
 
464
        case 'G':
465
        rsp_write_all_regs (buf);
466
        return;
467
      */
468
 
469
 
470
    case 'p':
471
      /* Read a register */
472
      hwp_read_reg(buf);
473
      return;
474
 
475
    case 'P':
476
      /* Write a register */
477
      hwp_write_reg(buf);
478
      return;
479
 
480
      /*
481
        case 'q':
482
        // Any one of a number of query packets
483
        rsp_query (buf);
484
        return;
485
 
486
        case 'Q':
487
        // Any one of a number of set packets
488
        rsp_set (buf);
489
        return;
490
      */
491
 
492
    default:
493
      /* Unknown commands are ignored */
494
      fprintf (stderr, "Warning: Unknown HWP request %s\n", buf->data);
495
      return;
496
    }
497
}       /* hwp_client_request () */
498
 
499
 
500
/*---------------------------------------------------------------------------*/
501
/*!Get a packet from the GDB client
502
 
503
   Modeled on the stub version supplied with GDB. The data is in a static
504
   buffer. The data should be copied elsewhere if it is to be preserved across
505
   a subsequent call to get_packet().
506
 
507
   Unlike the reference implementation, we don't deal with sequence
508
   numbers. GDB has never used them, and this implementation is only intended
509
   for use with GDB 6.8 or later. Sequence numbers were removed from the RSP
510
   standard at GDB 5.0.
511
 
512
   @return  A pointer to the static buffer containing the data                */
513
/*---------------------------------------------------------------------------*/
514
struct rsp_buf *hwp_get_packet(void)
515
{
516
  static struct rsp_buf  buf;           /* Survives the return */
517
 
518
  /* Keep getting packets, until one is found with a valid checksum */
519
  while (1)
520
    {
521
      unsigned char  checksum;          /* The checksum we have computed */
522
      int            count;             /* Index into the buffer */
523
      int            ch;                /* Current character */
524
 
525
      /* Wait around for the start character ('$'). Ignore all other
526
         characters */
527
      ch = get_hwp_rsp_char(hwp_client_fd);
528
      while (ch != '$')
529
        {
530
          if (-1 == ch)
531
            {
532
              return  NULL;             /* Connection failed */
533
            }
534
 
535
          ch = get_hwp_rsp_char(hwp_client_fd);
536
        }
537
 
538
      /* Read until a '#' or end of buffer is found */
539
      checksum =  0;
540
      count    =  0;
541
      while (count < HWP_BUF_MAX - 1)
542
        {
543
          ch = get_hwp_rsp_char(hwp_client_fd);
544
 
545
          /* Check for connection failure */
546
          if (-1 == ch)
547
            {
548
              return  NULL;
549
            }
550
 
551
          /* If we hit a start of line char begin all over again */
552
          if ('$' == ch)
553
            {
554
              checksum =  0;
555
              count    =  0;
556
 
557
              continue;
558
            }
559
 
560
          /* Break out if we get the end of line char */
561
          if ('#' == ch)
562
            {
563
              break;
564
            }
565
 
566
          /* Update the checksum and add the char to the buffer */
567
 
568
          checksum        = checksum + (unsigned char)ch;
569
          buf.data[count] = (char)ch;
570
          count           = count + 1;
571
        }
572
 
573
      /* Mark the end of the buffer with EOS - it's convenient for non-binary
574
         data to be valid strings. */
575
      buf.data[count] = 0;
576
      buf.len         = count;
577
 
578
      /* If we have a valid end of packet char, validate the checksum */
579
      if ('#' == ch)
580
        {
581
          unsigned char  xmitcsum;      /* The checksum in the packet */
582
 
583
          ch = get_hwp_rsp_char(hwp_client_fd);
584
          if (-1 == ch)
585
            {
586
              return  NULL;             /* Connection failed */
587
            }
588
          xmitcsum = hwp_hex(ch) << 4;
589
 
590
          ch = get_hwp_rsp_char(hwp_client_fd);
591
          if (-1 == ch)
592
            {
593
              return  NULL;             /* Connection failed */
594
            }
595
 
596
          xmitcsum += hwp_hex(ch);
597
 
598
          /* If the checksums don't match print a warning, and put the
599
             negative ack back to the client. Otherwise put a positive ack. */
600
          if (checksum != xmitcsum)
601
            {
602
              fprintf (stderr, "Warning: Bad HWP RSP checksum: Computed "
603
                       "0x%02x, received 0x%02x\n", checksum, xmitcsum);
604
 
605
              put_hwp_rsp_char (hwp_client_fd, '-');    /* Failed checksum */
606
            }
607
          else
608
            {
609
              put_hwp_rsp_char (hwp_client_fd, '+');    /* successful transfer */
610
              break;
611
            }
612
        }
613
      else
614
        {
615
          fprintf (stderr, "Warning: HWP RSP packet overran buffer\n");
616
        }
617
    }
618
 
619
  return &buf;                          /* Success */
620
 
621
}       /* hwp_get_packet () */
622
 
623
 
624
/*---------------------------------------------------------------------------*/
625
/*Single character get/set routines                                          */
626
/*---------------------------------------------------------------------------*/
627
void put_hwp_rsp_char(int fd, char  c)
628
{
629
  if (-1 == fd)
630
    {
631
      fprintf (stderr, "Warning: Attempt to write '%c' to unopened HWP RSP client: Ignored\n", c);
632
      return;
633
    }
634
 
635
  /* Write until successful (we retry after interrupts) or catastrophic
636
     failure. */
637
  while (1)
638
    {
639
      switch (write(fd, &c, sizeof (c)))
640
        {
641
        case -1:
642
          /* Error: only allow interrupts or would block */
643
          if ((EAGAIN != errno) && (EINTR != errno))
644
            {
645
              fprintf (stderr, "Warning: Failed to write to HWP RSP client: Closing client connection: %s\n",
646
                       strerror (errno));
647
              hwp_client_close();
648
              return;
649
            }
650
 
651
          break;
652
 
653
        case 0:
654
          break;                /* Nothing written! Try again */
655
 
656
        default:
657
          return;               /* Success, we can return */
658
        }
659
    }
660
}       /* put_hwp_rsp_char() */
661
 
662
 
663
 
664
int get_hwp_rsp_char(int fd)
665
{
666
  unsigned char  c;             /* The character read */
667
 
668
  if (-1 == fd)
669
    {
670
      fprintf (stderr, "Warning: Attempt to read from unopened HWP RSP client: Ignored\n");
671
      return  -1;
672
    }
673
 
674
  /* Read until successful (we retry after interrupts) or catastrophic
675
     failure. */
676
  while (1)
677
    {
678
      switch (read (fd, &c, sizeof (c)))
679
        {
680
        case -1:
681
          /* Error: only allow interrupts or would block */
682
          if ((EAGAIN != errno) && (EINTR != errno))
683
            {
684
              fprintf (stderr, "Warning: Failed to read from HWP RSP client: Closing client connection: %s\n",
685
                       strerror (errno));
686
              hwp_client_close();
687
              return  -1;
688
            }
689
 
690
          break;
691
 
692
        case 0:
693
          // EOF
694
          hwp_client_close();
695
          return  -1;
696
 
697
        default:
698
          return  c & 0xff;     /* Success, we can return (no sign extend!) */
699
        }
700
    }
701
}       /* get_hwp_rsp_char() */
702
 
703
 
704
/*---------------------------------------------------------------------------*/
705
/*!Read a single register
706
 
707
   The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
708
   (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a
709
   sequence of bytes in target endian order.
710
 
711
   Each byte is packed as a pair of hex digits.
712
 
713
   @param[in] buf  The original packet request. Reused for the reply.        */
714
/*---------------------------------------------------------------------------*/
715
void hwp_read_reg(struct rsp_buf *buf)
716
{
717
  unsigned int  regnum;
718
  uint32_t tmp;
719
  unsigned int errcode = APP_ERR_NONE;
720
 
721
  /* Break out the fields from the data */
722
  if (1 != sscanf (buf->data, "p%x", &regnum))
723
    {
724
      fprintf (stderr, "Warning: Failed to recognize HWP RSP read register command: \'%s\'\n", buf->data);
725
      hwp_put_str_packet (hwp_client_fd, "E01");
726
      return;
727
    }
728
 
729
  if((regnum == SPR_DMR2) && use_cached_dmr2)  // Should we use the cached DMR2 value?
730
    {
731
      tmp = cached_dmr2;
732
      errcode = APP_ERR_NONE;
733
      fprintf(stderr, "Using cached DMR2 value 0x%X\n", tmp);
734
    }
735
  else
736
    {
737
      /* Get the relevant register.  We assume the client is not GDB,
738
       * and that no register number translation is needed.
739
       */
740
      errcode = dbg_cpu0_read(regnum, &tmp);
741
    }
742
 
743
  if(errcode == APP_ERR_NONE) {
744
    hwp_reg2hex(tmp, buf->data);
745
    buf->len = strlen (buf->data);
746
    debug("Read reg 0x%x, got %s (0x%X), len %i\n", regnum, buf->data, tmp, buf->len);
747
    hwp_put_packet (hwp_client_fd, buf);
748
  }
749
  else {
750
    fprintf(stderr, "Error reading HWP register: %s\n", get_err_string(errcode));
751
    hwp_put_str_packet(hwp_client_fd, "E01");
752
  }
753
 
754
}       /* hwp_read_reg() */
755
 
756
 
757
/*---------------------------------------------------------------------------*/
758
/*!Write a single register
759
 
760
   The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
761
   (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a
762
   sequence of bytes in target endian order.
763
 
764
   Each byte is packed as a pair of hex digits.
765
 
766
   @param[in] buf  The original packet request.                              */
767
/*---------------------------------------------------------------------------*/
768
void hwp_write_reg (struct rsp_buf *buf)
769
{
770
  unsigned int  regnum;
771
  char          valstr[9];              /* Allow for EOS on the string */
772
  unsigned int  errcode = APP_ERR_NONE;
773 56 nyawn
  int dcridx;
774
  uint32_t val, cc, ct;
775 51 nyawn
 
776
  /* Break out the fields from the data */
777
  if (2 != sscanf (buf->data, "P%x=%8s", &regnum, valstr))
778
    {
779
      fprintf (stderr, "Warning: Failed to recognize RSP write register command: %s\n", buf->data);
780
      hwp_put_str_packet (hwp_client_fd, "E01");
781
      return;
782
    }
783
 
784
  /* Set the relevant register.  We assume that the client is not
785
   * GDB, and no register number translation is needed. */
786 56 nyawn
  val =  hwp_hex2reg(valstr);
787
  errcode = dbg_cpu0_write(regnum, val);
788 51 nyawn
 
789
  if(errcode == APP_ERR_NONE) {
790
    debug("Wrote reg 0x%X with val 0x%X (%s)\n", regnum, hwp_hex2reg(valstr), valstr);
791
    hwp_put_str_packet (hwp_client_fd, "OK");
792
  }
793
  else {
794
    fprintf(stderr, "Error writing register: %s\n", get_err_string(errcode));
795
    hwp_put_str_packet(hwp_client_fd, "E01");
796
  }
797
 
798 56 nyawn
  /* A bit of hackery: Determine if this write enables a comparison on a DCR.
799
   * If so, then we mark this HWP as in use, so that GDB/RSP cannot use it.
800
   * Note that there's no point making the HWP client check which watchpoints are in
801
   * use - GDB only sets HWP as it is starting the CPU, and clears them
802
   * immediately after a stop.  So as far as the HWP client would see, GDB/RSP
803
   * never uses any watchpoints.
804
   */
805
 
806
  if((regnum >= SPR_DCR(0)) && (regnum <= SPR_DCR(7)))
807
    {
808
      dcridx = regnum - SPR_DCR(0);
809
      /* If the 'compare condition' (cc) or 'compare to' (ct) are 0,
810
       * then matching is disabled and we can mark this HWP not in use.
811
       */
812
      cc = val & 0x0E;
813
      ct = val & 0xE0;
814
      if ((cc == 0) || (ct == 0))
815
        hwp_set_in_use(dcridx, 0);
816
      else
817
        hwp_set_in_use(dcridx, 1);
818
    }
819
 
820 51 nyawn
}       /* hwp_write_reg() */
821
 
822
/*---------------------------------------------------------------------------*/
823
/*!Convenience to put a constant string packet
824
 
825
   param[in] str  The text of the packet                                     */
826
/*---------------------------------------------------------------------------*/
827
void hwp_put_str_packet (int fd, const char *str)
828
{
829
  struct rsp_buf  buf;
830
  int             len = strlen (str);
831
 
832
  /* Construct the packet to send, so long as string is not too big,
833
     otherwise truncate. Add EOS at the end for convenient debug printout */
834
 
835
  if (len >= HWP_BUF_MAX)
836
    {
837
      fprintf (stderr, "Warning: String %s too large for HWP RSP packet: truncated\n", str);
838
      len = HWP_BUF_MAX - 1;
839
    }
840
 
841
  strncpy (buf.data, str, len);
842
  buf.data[len] = 0;
843
  buf.len       = len;
844
 
845
  hwp_put_packet (fd, &buf);
846
 
847
}       /* hwp_put_str_packet () */
848
 
849
/*---------------------------------------------------------------------------*/
850
/*!Send a packet to the GDB client
851
 
852
   Modeled on the stub version supplied with GDB. Put out the data preceded by
853
   a '$', followed by a '#' and a one byte checksum. '$', '#', '*' and '}' are
854
   escaped by preceding them with '}' and then XORing the character with
855
   0x20.
856
 
857
   @param[in] buf  The data to send                                          */
858
/*---------------------------------------------------------------------------*/
859
void hwp_put_packet (int fd, struct rsp_buf *buf)
860
{
861
  int  ch;                              /* Ack char */
862
 
863
  /* Construct $<packet info>#<checksum>. Repeat until the GDB client
864
     acknowledges satisfactory receipt. */
865
  do
866
    {
867
      unsigned char checksum = 0;        /* Computed checksum */
868
      int           count    = 0;        /* Index into the buffer */
869
 
870
      debug("Putting %s\n", buf->data);
871
 
872
      put_hwp_rsp_char (fd, '$');               /* Start char */
873
 
874
      /* Body of the packet */
875
      for (count = 0; count < buf->len; count++)
876
        {
877
          unsigned char  ch = buf->data[count];
878
 
879
          /* Check for escaped chars */
880
          if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch))
881
            {
882
              ch       ^= 0x20;
883
              checksum += (unsigned char)'}';
884
              put_hwp_rsp_char (fd, '}');
885
            }
886
 
887
          checksum += ch;
888
          put_hwp_rsp_char (fd, ch);
889
        }
890
 
891
      put_hwp_rsp_char (fd, '#');               /* End char */
892
 
893
      /* Computed checksum */
894
      put_hwp_rsp_char (fd, hexchars[checksum >> 4]);
895
      put_hwp_rsp_char (fd, hexchars[checksum % 16]);
896
 
897
      /* Check for ack or connection failure */
898
      ch = get_hwp_rsp_char (fd);
899
      if (-1 == ch)
900
        {
901
          return;                       /* Fail the put silently. */
902
        }
903
    }
904
  while ('+' != ch);
905
 
906
}       /* hwp_put_packet() */
907
 
908
 
909
unsigned long int hwp_hex2reg (char *buf)
910
{
911
  int                n;         /* Counter for digits */
912
  unsigned long int  val = 0;    /* The result */
913
 
914
  for (n = 0; n < 8; n++)
915
    {
916
#ifdef WORDSBIGENDIAN
917
      int  nyb_shift = n * 4;
918
#else
919
      int  nyb_shift = 28 - (n * 4);
920
#endif
921
      val |= hwp_hex(buf[n]) << nyb_shift;
922
    }
923
 
924
  return val;
925
 
926
}       /* hwp_hex2reg() */
927
 
928
 
929
void hwp_reg2hex(unsigned long int val, char *buf)
930
{
931
  int  n;                       /* Counter for digits */
932
 
933
  for (n = 0; n < 8; n++)
934
    {
935
#ifdef WORDSBIGENDIAN
936
      int  nyb_shift = n * 4;
937
#else
938
      int  nyb_shift = 28 - (n * 4);
939
#endif
940
      buf[n] = hexchars[(val >> nyb_shift) & 0xf];
941
    }
942
 
943
  buf[8] = 0;                    /* Useful to terminate as string */
944
 
945
}       /* hwp_reg2hex() */
946
 
947
 
948
int hwp_hex(int c)
949
{
950
  return  ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 :
951
          ((c >= '0') && (c <= '9')) ? c - '0' :
952
          ((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1;
953
 
954
}       /* hwp_hex() */
955
 
956
/* ---------------------------------------------------------------------- */
957
/* Functions to report stop and start to the client.                      */
958
/* Not strictly correct RSP protocol.                                     */
959
/*------------------------------------------------------------------------*/
960
 
961
void hwp_report_stop(void)
962
{
963
  struct rsp_buf  buf;
964
  uint32_t ppcval;
965
 
966
  // Read the PPC
967
  dbg_cpu0_read(SPR_PPC, &ppcval);
968
 
969
  debug("HWP reporting stop, PPC = 0x%X\n", ppcval);
970
 
971
  /* Construct a signal received packet */
972
  buf.data[0] = 'S';
973
  buf.data[1] = hexchars[ppcval >> 4];
974
  buf.data[2] = hexchars[ppcval % 16];
975
  buf.data[3] = 0;
976
  buf.len     = strlen (buf.data);
977
 
978
  hwp_put_packet(hwp_client_fd, &buf);
979
 
980
}       /* rsp_report_exception () */
981
 
982
 
983
void hwp_report_run(void)
984
{
985
  struct rsp_buf  buf;
986
 
987
  // Construct a 'run' packet.  This is completely non-standard, non-RSP, made up.
988
  buf.data[0] = 'R';
989
  buf.data[1] = 'U';
990
  buf.data[2] = 'N';
991
  buf.data[3] = 0;
992
  buf.len     = strlen (buf.data);
993
 
994
  hwp_put_packet(hwp_client_fd, &buf);
995
 
996
}  /* hwp_report_run() */
997
 
998 56 nyawn
/* Used by the HWP server to indicate which HWP are
999
 * in long-term use by an external client
1000
 */
1001
void hwp_set_in_use(unsigned int wp, unsigned char inuse)
1002
{
1003
  if(wp < HWP_MAX_WP)
1004
    {
1005
      hwp_in_use[wp] = inuse;
1006
      debug("HWP setting wp %i status to %i\n", wp, inuse);
1007
    }
1008
  else
1009
    fprintf(stderr, "ERROR! value %i out of range when setting HWP in use!\n", wp);
1010
}
1011
 
1012
/* Called by the RSP server to get any one unused HWP.
1013
 * This will only be called immediately before a 'step'
1014
 * or 'continue,' and the HWP will be disabled as soon
1015
 * as the CPU returns control to the RSP server.
1016
 * Returns -1 if no HWP available.
1017
 */
1018
int hwp_get_available_watchpoint(void)
1019
{
1020
  int i;
1021
  int ret = -1;
1022
 
1023
  for(i = 0; i < HWP_MAX_WP; i++)
1024
    {
1025
      if(hwp_in_use[i] == 0)
1026
        {
1027
          ret = i;
1028
          hwp_in_use[i] = 1;
1029
 
1030
          break;
1031
        }
1032
    }
1033
  debug("HWP granting wp %i to GDB/RSP\n", ret);
1034
  return ret;
1035
}
1036
 
1037
/* Called by the RSP server to indicate it is no longer
1038
 * using a watchpoint previously granted by
1039
 * hwp_get_available_watchpoint()
1040
 */
1041
void hwp_return_watchpoint(int wp)
1042
{
1043
  if(wp >= HWP_MAX_WP)
1044
    {
1045
      fprintf(stderr, "ERROR! WP value %i out of range in hwp_return_watchpoint()!\n", wp);
1046
    }
1047
  else
1048
    {
1049
      if(hwp_in_use[wp] != 0)
1050
        {
1051
          hwp_in_use[wp] = 0;
1052
          debug("HWP got wp %i back from GDB/RSP\n", wp);
1053
        }
1054
      else
1055
        fprintf(stderr, "ERROR! hwp_return_watchpoint() returning wp %i, not in use!\n", wp);
1056
    }
1057
}

powered by: WebSVN 2.1.0

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