1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 ******************************************************************************/
22 
23 /****************************************************************************
24 
25 		THIS SOFTWARE IS NOT COPYRIGHTED
26 
27    HP offers the following for use in the public domain.  HP makes no
28    warranty with regard to the software or it's performance and the
29    user accepts the software "AS IS" with all faults.
30 
31    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
32    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
33    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34 
35 ****************************************************************************/
36 
37 /****************************************************************************
38  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
39  *
40  *  Module name: remcom.c $
41  *  Revision: 1.34 $
42  *  Date: 91/03/09 12:29:49 $
43  *  Contributor:     Lake Stevens Instrument Division$
44  *
45  *  Description:     low level support for gdb debugger. $
46  *
47  *  Considerations:  only works on target hardware $
48  *
49  *  Written by:      Glenn Engel $
50  *  ModuleState:     Experimental $
51  *
52  *  NOTES:           See Below $
53  *
54  *  Modified for SPARC by Stu Grossman, Cygnus Support.
55  *
56  *  This code has been extensively tested on the Fujitsu SPARClite demo board.
57  *
58  *  To enable debugger support, two things need to happen.  One, a
59  *  call to set_debug_traps() is necessary in order to allow any breakpoints
60  *  or error conditions to be properly intercepted and reported to gdb.
61  *  Two, a breakpoint needs to be generated to begin communication.  This
62  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
63  *  simulates a breakpoint by executing a trap #1.
64  *
65  *************
66  *
67  *    The following gdb commands are supported:
68  *
69  * command          function                               Return value
70  *
71  *    g             return the value of the CPU registers  hex data or ENN
72  *    G             set the value of the CPU registers     OK or ENN
73  *
74  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
75  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
76  *
77  *    c             Resume at current address              SNN   ( signal NN)
78  *    cAA..AA       Continue at address AA..AA             SNN
79  *
80  *    s             Step one instruction                   SNN
81  *    sAA..AA       Step one instruction from AA..AA       SNN
82  *
83  *    k             kill
84  *
85  *    ?             What was the last sigval ?             SNN   (signal NN)
86  *
87  * All commands and responses are sent with a packet which includes a
88  * checksum.  A packet consists of
89  *
90  * $<packet info>#<checksum>.
91  *
92  * where
93  * <packet info> :: <characters representing the command or response>
94  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
95  *
96  * When a packet is received, it is first acknowledged with either '+' or '-'.
97  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
98  *
99  * Example:
100  *
101  * Host:                  Reply:
102  * $m0,10#2a               +$00010203040506070809101112131415#42
103  *
104  ****************************************************************************/
105 #ifdef XAF_ENABLE_NON_HIKEY
106 #include "xf.h"
107 #else
108 #include <string.h>
109 #include <signal.h>
110 #include <stdint.h>
111 #include <xtensa/xtruntime.h>
112 #endif
113 #include "xtensa-defs.h"
114 
115 /*******************************************************************************
116  * Ring-buffer definition
117  ******************************************************************************/
118 
119 #define RING_SIZE           256
120 
121 struct ring {
122 	unsigned char head;
123 	unsigned char fill1[63];
124 	unsigned char tail;
125 	unsigned char fill2[63];
126 	unsigned char data[RING_SIZE];
127 };
128 
129 #define GDB_INVALIDATE(p)     \
130     xthal_dcache_region_invalidate((void *)(p), sizeof(*p))
131 
132 #define GDB_FLUSH(p)          \
133     xthal_dcache_region_writeback((void *)(p), sizeof(*p))
134 
ring_next_head(const volatile struct ring * ring)135 static inline unsigned int ring_next_head(const volatile struct ring *ring)
136 {
137 	return (ring->head + 1) & (RING_SIZE - 1);
138 }
139 
ring_next_tail(const volatile struct ring * ring)140 static inline unsigned int ring_next_tail(const volatile struct ring *ring)
141 {
142 	return (ring->tail + 1) & (RING_SIZE - 1);
143 }
144 
ring_have_space(const volatile struct ring * ring)145 static inline int ring_have_space(const volatile struct ring *ring)
146 {
147     /* ...invalidate tail pointer of tx-ring (updated by host) */
148     GDB_INVALIDATE(&ring->tail);
149 
150 	return ring_next_head(ring) != ring->tail;
151 }
152 
ring_have_data(const volatile struct ring * ring)153 static inline int ring_have_data(const volatile struct ring *ring)
154 {
155     /* ...invalidate head pointer of rx-ring (updated by host) */
156     GDB_INVALIDATE(&ring->head);
157 
158 	return ring->head != ring->tail;
159 }
160 #ifdef XAF_ENABLE_NON_HIKEY
161 #define DEBUG_RX_BASE   XF_CFG_GDB_RING_RX
162 #define DEBUG_TX_BASE   XF_CFG_GDB_RING_TX
163 #else
164 //#define DEBUG_RX_BASE (0x72000000)
165 //#define DEBUG_TX_BASE (0x72000800)
166 #define DEBUG_RX_BASE (0x6FFFF000)
167 #define DEBUG_TX_BASE (0x6FFFF800)
168 #endif
169 
170 volatile struct ring * const rx = (void *)DEBUG_RX_BASE;
171 volatile struct ring * const tx = (void *)DEBUG_TX_BASE;
172 
init_debug_comm(void)173 void init_debug_comm(void)
174 {
175 	rx->head = rx->tail = 0;
176 	tx->head = tx->tail = 0;
177     GDB_FLUSH(&rx->head);
178     GDB_FLUSH(&rx->tail);
179     GDB_FLUSH(&tx->head);
180     GDB_FLUSH(&tx->tail);
181 }
182 
183 /* ...functions defined in asm code */
184 extern void breakpoint(void);
185 extern void init_debug_entry(void);
186 
poll_debug_ring(void)187 void poll_debug_ring(void)
188 {
189 	if (ring_have_data(rx)) {
190 		breakpoint();
191 	}
192 }
193 
putDebugChar(char c)194 static void putDebugChar(char c)
195 {
196 	while (!ring_have_space(tx))
197 		;
198 
199 	tx->data[tx->head] = c;
200 
201     /* ...flush data buffer to main memory */
202     GDB_FLUSH(&tx->data[tx->head]);
203 
204 	tx->head = ring_next_head(tx);
205 
206     /* ...flush head pointer to main memory */
207     GDB_FLUSH(&tx->head);
208 }
209 
getDebugChar(void)210 static int getDebugChar(void)
211 {
212 	int v;
213 	while (!ring_have_data(rx))
214 		;
215 
216     /* ...inavlidate data buffer */
217     GDB_INVALIDATE(&rx->data[rx->tail]);
218 
219 	v = rx->data[rx->tail];
220 	rx->tail = ring_next_tail(rx);
221 
222     /* ...update tail index */
223     GDB_FLUSH(&rx->tail);
224 
225 	return v;
226 }
227 
228 /************************************************************************/
229 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
230 /* at least NUMREGBYTES*2 are needed for register packets */
231 #define BUFMAX 256
232 
233 #ifdef USE_GDBSTUB
234 #define bulk_data __attribute__((section (".ddr0.data")))
235 #else
236 #define bulk_data
237 #endif
238 uint32_t stack[STACK_SIZE / sizeof(uint32_t)] bulk_data;
239 static uint8_t sregs_read[32] bulk_data;
240 static uint8_t sregs_mod[32] bulk_data;
241 static uint8_t sregs_late[32] bulk_data;
242 uint32_t sregs[256] bulk_data;
243 uint32_t aregs[XCHAL_NUM_AREGS] bulk_data;
244 static uint8_t remcomInBuffer[BUFMAX] bulk_data;
245 static uint8_t remcomOutBuffer[BUFMAX] bulk_data;
246 
247 static const char hexchars[]="0123456789abcdef";
248 
249 /* Convert ch from a hex digit to an int */
250 
hex(unsigned char ch)251 static int hex(unsigned char ch)
252 {
253 	if (ch >= 'a' && ch <= 'f')
254 		return ch-'a'+10;
255 	if (ch >= '0' && ch <= '9')
256 		return ch-'0';
257 	if (ch >= 'A' && ch <= 'F')
258 		return ch-'A'+10;
259 	return -1;
260 }
261 
262 /* scan for the sequence $<data>#<checksum>     */
263 
getpacket(void)264 unsigned char *getpacket(void)
265 {
266 	unsigned char *buffer = &remcomInBuffer[0];
267 	unsigned char checksum;
268 	unsigned char xmitcsum;
269 	int count;
270 	char ch;
271 
272 	while (1) {
273 		/* wait around for the start character, ignore all other characters */
274 		while ((ch = getDebugChar ()) != '$')
275 			;
276 
277 retry:
278 		checksum = 0;
279 		xmitcsum = -1;
280 		count = 0;
281 
282 		/* now, read until a # or end of buffer is found */
283 		while (count < BUFMAX - 1) {
284 			ch = getDebugChar ();
285 			if (ch == '$')
286 				goto retry;
287 			if (ch == '#')
288 				break;
289 			checksum = checksum + ch;
290 			buffer[count] = ch;
291 			count = count + 1;
292 		}
293 		buffer[count] = 0;
294 
295 		if (ch == '#') {
296 			ch = getDebugChar ();
297 			xmitcsum = hex (ch) << 4;
298 			ch = getDebugChar ();
299 			xmitcsum += hex (ch);
300 
301 			if (checksum != xmitcsum) {
302 				putDebugChar ('-');	/* failed checksum */
303 			} else {
304 				putDebugChar ('+');	/* successful transfer */
305 
306 				/* if a sequence char is present, reply the sequence ID */
307 				if (buffer[2] == ':') {
308 					putDebugChar (buffer[0]);
309 					putDebugChar (buffer[1]);
310 
311 					return &buffer[3];
312 				}
313 
314 				return &buffer[0];
315 			}
316 		}
317 	}
318 }
319 
320 /* send the packet in buffer.  */
321 
putpacket(uint8_t * buffer)322 static void putpacket(uint8_t *buffer)
323 {
324 	unsigned char checksum;
325 	int count;
326 	unsigned char ch;
327 
328 	/*  $<packet info>#<checksum>. */
329 	do {
330 		putDebugChar('$');
331 		checksum = 0;
332 		count = 0;
333 
334 		while ((ch = buffer[count]) != 0) {
335 			putDebugChar(ch);
336 			checksum += ch;
337 			count += 1;
338 		}
339 
340 		putDebugChar('#');
341 		putDebugChar(hexchars[checksum >> 4]);
342 		putDebugChar(hexchars[checksum & 0xf]);
343 
344 	} while (getDebugChar() != '+');
345 }
346 
347 /* Indicate to caller of mem2hex or hex2mem that there has been an
348    error.  */
349 volatile int mem_err = 0;
350 
351 /* Convert the memory pointed to by mem into hex, placing result in buf.
352  * Return a pointer to the last char put in buf (null), in case of mem fault,
353  * return 0.
354  */
355 
mem2hex(const void * mem_,uint8_t * buf,int count)356 static uint8_t * mem2hex(const void *mem_, uint8_t *buf, int count)
357 {
358 	const unsigned char *mem = mem_;
359 	unsigned char ch;
360 
361 	mem_err = 0;
362 	while (count-- > 0) {
363 #ifdef __XTENSA__
364 		unsigned long v;
365 		unsigned long addr = (unsigned long)mem;
366 		asm volatile ("_l32i	%0, %1, 0\n"
367 			      : "=r"(v)
368 			      : "r"(addr & ~3)
369 			      : "memory");
370 		ch = v >> (addr & 3) * 8;
371 #endif
372 		mem++;
373 		if (mem_err)
374 			return NULL;
375 		*buf++ = hexchars[ch >> 4];
376 		*buf++ = hexchars[ch & 0xf];
377 	}
378 
379 	*buf = 0;
380 
381 	return buf;
382 }
383 
384 /* convert the hex array pointed to by buf into binary to be placed in mem
385  * return a pointer to the character AFTER the last byte written */
386 
hex2mem(const uint8_t * buf,void * mem_,int count)387 static uint8_t * hex2mem(const uint8_t *buf, void *mem_, int count)
388 {
389 	uint8_t *mem = mem_;
390 	int i;
391 	uint8_t ch;
392 
393 	if ((unsigned long)mem >= 0xece80000)
394 		return NULL;
395 
396 	mem_err = 0;
397 	for (i=0; i<count; i++) {
398 		ch = hex(*buf++) << 4;
399 		ch |= hex(*buf++);
400 #ifdef __XTENSA__
401 		unsigned long tmp;
402 		unsigned long addr = (unsigned long)mem;
403 		asm volatile ("_l32i	%0, %1, 0\n"
404 			      "and	%0, %0, %2\n"
405 			      "or	%0, %0, %3\n"
406 			      "_s32i	%0, %1, 0\n"
407 			      "dhwb	%1, 0\n"
408 			      "ihi	%1, 0\n"
409 			      : "=r"(tmp)
410 			      : "r"(addr & ~3), "r"(0xffffffff ^ (0xff << (addr & 3) * 8)), "r"(ch << (addr & 3) * 8)
411 			      : "memory");
412 #endif
413 		mem++;
414 		if (mem_err)
415 			return NULL;
416 	}
417 
418 	return mem;
419 }
420 
421 /*
422  * While we find nice hex chars, build an int.
423  * Return number of chars processed.
424  */
425 
hexToInt(uint8_t ** ptr,int * intValue)426 static int hexToInt(uint8_t **ptr, int *intValue)
427 {
428 	int numChars = 0;
429 	int hexValue;
430 
431 	*intValue = 0;
432 
433 	while (**ptr) {
434 		hexValue = hex(**ptr);
435 		if (hexValue < 0)
436 			break;
437 
438 		*intValue = (*intValue << 4) | hexValue;
439 		numChars ++;
440 
441 		(*ptr)++;
442 	}
443 
444 	return (numChars);
445 }
446 
test_bit(const uint8_t * p,int bit)447 static inline int test_bit(const uint8_t *p, int bit)
448 {
449 	return (p[bit / 8] >> (bit & 0x7)) & 1;
450 }
set_bit(uint8_t * p,int bit)451 static inline int set_bit(uint8_t *p, int bit)
452 {
453 	return (p[bit / 8] |= 1u << (bit & 0x7));
454 }
455 
mark_read(int sr)456 static inline void mark_read(int sr)
457 {
458 	set_bit(sregs_read, sr);
459 }
is_read(int sr)460 static inline int is_read(int sr)
461 {
462 	return test_bit(sregs_read, sr);
463 }
mark_mod(int sr)464 static inline void mark_mod(int sr)
465 {
466 	set_bit(sregs_mod, sr);
467 }
is_mod(int sr)468 static inline int is_mod(int sr)
469 {
470 	return test_bit(sregs_mod, sr);
471 }
mark_late(int sr)472 static inline void mark_late(int sr)
473 {
474 	set_bit(sregs_late, sr);
475 }
is_late(int sr)476 static inline int is_late(int sr)
477 {
478 	return test_bit(sregs_late, sr);
479 }
480 
read_sr(int sr)481 static void read_sr(int sr)
482 {
483 	if (!is_read(sr)) {
484 #ifdef __XTENSA__
485 		uint32_t val;
486 		asm volatile ("movi	a3, 1f + 1\n"
487 			      "s8i	%1, a3, 0\n"
488 			      "dhwb	a3, 0\n"
489 			      "ihi	a3, 0\n"
490 			      "isync\n"
491 			      "1:\n"
492 			      "rsr	%0, lbeg\n"
493 			      : "=r"(val)
494 			      : "r"(sr)
495 			      : "a3", "memory");
496 		sregs[sr] = val;
497 #endif
498 		mark_read(sr);
499 	}
500 }
501 
write_sr(int sr)502 static void write_sr(int sr)
503 {
504 #ifdef __XTENSA__
505 	asm volatile ("movi	a3, 1f + 1\n"
506 		      "s8i	%1, a3, 0\n"
507 		      "dhwb	a3, 0\n"
508 		      "ihi	a3, 0\n"
509 		      "isync\n"
510 		      "1:\n"
511 		      "wsr	%0, lbeg\n"
512 		      :
513 		      : "r"(sregs[sr]), "r"(sr)
514 		      : "a3", "memory");
515 #endif
516 }
517 
restore_sr(void)518 static void restore_sr(void)
519 {
520 	int i;
521 	for (i = 0; i < 256; ++i)
522 		if (is_mod(i) && !is_late(i))
523 			write_sr(i);
524 }
525 
526 extern void *_xtos_exc_handler_table[];
527 void fault_handler(void);
528 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
529 
handle_exception(void)530 void handle_exception(void)
531 {
532 	int sigval = 0;
533 	int addr;
534 	int length;
535 	uint8_t *ptr;
536 	unsigned i;
537 	const unsigned windowbase = 4 * sregs[WINDOWBASE];
538 	uint8_t stop_status[4] = "Sxx";
539 #ifdef LIBC_LEVEL1_HANDLER
540 	static const int cause[] = {
541 		EXCCAUSE_LOAD_STORE_ERROR,
542 		EXCCAUSE_LOAD_STORE_DATA_ERROR,
543 		EXCCAUSE_LOAD_STORE_ADDR_ERROR,
544 		EXCCAUSE_DTLB_MISS,
545 		EXCCAUSE_DTLB_MULTIHIT,
546 		EXCCAUSE_LOAD_PROHIBITED,
547 		EXCCAUSE_STORE_PROHIBITED,
548 	};
549 	_xtos_handler handler[sizeof(cause) / sizeof(cause[0])];
550 
551 	for (i = 0; i < ARRAY_SIZE(cause); ++i) {
552 		handler[i] = _xtos_exc_handler_table[cause[i]];
553 		_xtos_exc_handler_table[cause[i]] = fault_handler;
554 	}
555 #endif
556 	memcpy(sregs_read, sregs_late, sizeof(sregs_read));
557 	memset(sregs_mod, 0, sizeof(sregs_mod));
558 
559 	sigval = 5;
560 	stop_status[1] = hexchars[sigval >> 4];
561 	stop_status[2] = hexchars[sigval & 0xf];
562 
563 	if (sregs[DEBUGCAUSE] & DEBUGCAUSE_ICOUNT_MASK) {
564 		sregs[ICOUNTLEVEL] = 0;
565 		mark_mod(ICOUNTLEVEL);
566 	}
567 	putpacket(stop_status);
568 
569 	while (1) {
570 		remcomOutBuffer[0] = 0;
571 
572 		ptr = getpacket();
573 		switch (*ptr++) {
574 		case '?':
575 			memcpy(remcomOutBuffer, stop_status, sizeof(stop_status));
576 			break;
577 
578 		case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
579 			/* try to read optional parameter, pc unchanged if no parm */
580 
581 			if (hexToInt(&ptr, &addr))
582 				sregs[DEBUG_PC] = addr;
583 			goto out;
584 
585 		case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
586 			/* Try to read %x,%x.  */
587 
588 			if (hexToInt(&ptr, &addr) && *ptr++ == ',' &&
589 			    hexToInt(&ptr, &length)) {
590 				if (mem2hex((void *)addr, remcomOutBuffer, length))
591 					break;
592 
593 				strcpy((char *)remcomOutBuffer, "E03");
594 			} else {
595 				strcpy((char *)remcomOutBuffer, "E01");
596 			}
597 			break;
598 
599 		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
600 			/* Try to read '%x,%x:'.  */
601 
602 			if (hexToInt(&ptr, &addr) && *ptr++ == ',' &&
603 			    hexToInt(&ptr, &length) && *ptr++ == ':') {
604 				if (hex2mem(ptr, (void *)addr, length))
605 					strcpy((char *)remcomOutBuffer, "OK");
606 				else
607 					strcpy((char *)remcomOutBuffer, "E03");
608 			} else {
609 				strcpy((char *)remcomOutBuffer, "E02");
610 			}
611 			break;
612 
613 		case 'p': /* pAA..AA read register number AA..AA */
614 			if (hexToInt(&ptr, &addr)) {
615 				if (addr < 0x10) { /* read address register in the current window */
616 					mem2hex(aregs + addr, remcomOutBuffer, 4);
617 				} else if (addr == 0x20) { /* read PC */
618 					mem2hex(sregs + DEBUG_PC, remcomOutBuffer, 4);
619 				} else if (addr >= 0x100 && addr < 0x100 + XCHAL_NUM_AREGS) { /* read address register by absolute index */
620 					mem2hex(aregs + ((addr - windowbase) & 0xff), remcomOutBuffer, 4);
621 				} else if (addr >= 0x200 && addr < 0x300) { /* read special register */
622 					addr &= 0xff;
623 					read_sr(addr);
624 					mem2hex(sregs + addr, remcomOutBuffer, 4);
625 				} else if (addr >= 0x300 && addr < 0x400) { /* TODO read user register */
626 					strcpy((char *)remcomOutBuffer, "deadbabe");
627 				} else { /* unexpected register number */
628 					strcpy((char *)remcomOutBuffer, "E00");
629 				}
630 			}
631 			break;
632 
633 		case 'P': /* PAA..AA=VV..VV  Set register number AA..AA to a value VV..VV */
634 			if (hexToInt(&ptr, &addr) && *(ptr++) == '=') {
635 				int ok = 1;
636 
637 				if (addr < 0x10) {
638 					hex2mem(ptr, aregs + addr, 4);
639 				} else if (addr == 0x20) {
640 					hex2mem(ptr, sregs + DEBUG_PC, 4);
641 				} else if (addr >= 0x100 && addr < 0x100 + XCHAL_NUM_AREGS) {
642 					hex2mem(ptr, aregs + ((addr - windowbase) & 0xff), 4);
643 				} else if (addr >= 0x200 && addr < 0x300) {
644 					addr &= 0xff;
645 					hex2mem(ptr, sregs + addr, 4);
646 					mark_read(addr);
647 					mark_mod(addr);
648 				} else {
649 					ok = 0;
650 					strcpy((char *)remcomOutBuffer, "E00");
651 				}
652 				if (ok)
653 					strcpy((char *)remcomOutBuffer, "OK");
654 			}
655 			break;
656 
657 		case 'q': /* generic query */
658 			if (strncmp((char *)ptr, "Supported", 9) == 0)
659 				strcpy((char *)remcomOutBuffer, "PacketSize=100"); /* must match BUFMAX */
660 			break;
661 
662 		case 's': /* s[AA..AA] Single step */
663 			if (hexToInt(&ptr, &addr))
664 				sregs[DEBUG_PC] = addr;
665 			sregs[ICOUNT] = 0xfffffffe;
666 			mark_mod(ICOUNT);
667 			sregs[ICOUNTLEVEL] = XCHAL_DEBUGLEVEL;
668 			mark_mod(ICOUNTLEVEL);
669 			goto out;
670 
671 		case 'Z': /* insert HW breakpoint*/
672 			switch (*ptr++) {
673 			case '1':
674 				read_sr(IBREAKENABLE);
675 				if (*ptr++ == ',' && hexToInt(&ptr, &addr) &&
676 				    *ptr++ == ',' && hexToInt(&ptr, &length) &&
677 				    *ptr == 0) {
678 					for (i = 0; i < XCHAL_NUM_IBREAK; ++i) {
679 						if (!(sregs[IBREAKENABLE] & (1 << i)) ||
680 						    sregs[IBREAKA + i] == addr) {
681 							sregs[IBREAKA + i] = addr;
682 							mark_mod(IBREAKA + i);
683 							sregs[IBREAKENABLE] |= (1 << i);
684 							mark_mod(IBREAKENABLE);
685 							break;
686 						}
687 					}
688 					if (i == XCHAL_NUM_IBREAK)
689 						strcpy((char *)remcomOutBuffer, "E02");
690 					else
691 						strcpy((char *)remcomOutBuffer, "OK");
692 				} else {
693 					strcpy((char *)remcomOutBuffer, "E01");
694 				}
695 				break;
696 			}
697 			break;
698 
699 		case 'z': /* remove HW breakpoint */
700 			switch (*ptr++) {
701 			case '1':
702 				read_sr(IBREAKENABLE);
703 				if (*ptr++ == ',' && hexToInt(&ptr, &addr) &&
704 				    *ptr++ == ',' && hexToInt(&ptr, &length)) {
705 					for (i = 0; i < XCHAL_NUM_IBREAK; ++i) {
706 						read_sr(IBREAKA + i);
707 						if (sregs[IBREAKENABLE] & (1 << i) &&
708 						    sregs[IBREAKA + i] == addr) {
709 							sregs[IBREAKENABLE] &= ~(1 << i);
710 							mark_mod(IBREAKENABLE);
711 							break;
712 						}
713 					}
714 					if (i == XCHAL_NUM_IBREAK)
715 						strcpy((char *)remcomOutBuffer, "E02");
716 					else
717 						strcpy((char *)remcomOutBuffer, "OK");
718 				} else {
719 					strcpy((char *)remcomOutBuffer, "E01");
720 				}
721 				break;
722 			}
723 			break;
724 		}
725 
726 		/* reply to the request */
727 		putpacket(remcomOutBuffer);
728 	}
729 out:
730 #ifdef LIBC_LEVEL1_HANDLER
731 	for (i = 0; i < ARRAY_SIZE(cause); ++i) {
732 		_xtos_exc_handler_table[cause[i]] = handler[i];
733 	}
734 #endif
735 	restore_sr();
736 }
737 
init_gdbstub(void)738 void init_gdbstub(void)
739 {
740 	mark_late(LBEG);
741 	mark_late(LEND);
742 	mark_late(LCOUNT);
743 	mark_late(SAR);
744 	mark_late(WINDOWBASE);
745 	mark_late(WINDOWSTART);
746 	mark_late(DEBUG_PC);
747 	mark_late(EXCSAVE_1);
748 	mark_late(PS);
749 	mark_late(EXCCAUSE);
750 	mark_late(DEBUGCAUSE);
751 	mark_late(EXCVADDR);
752 #ifdef __XTENSA__
753 	init_debug_comm();
754 	init_debug_entry();
755 #endif
756 }
757