Procházet zdrojové kódy

[GDB] Atomic read/write for device memory

tags/v0.9.4
Stefan Hajnoczi před 16 roky
rodič
revize
9ec3ff95f0
1 změnil soubory, kde provedl 53 přidání a 13 odebrání
  1. 53
    13
      src/core/gdbstub.c

+ 53
- 13
src/core/gdbstub.c Zobrazit soubor

@@ -27,7 +27,7 @@
27 27
 #include <stddef.h>
28 28
 #include <stdio.h>
29 29
 #include <ctype.h>
30
-#include <assert.h>
30
+#include <byteswap.h>
31 31
 #include <gpxe/process.h>
32 32
 #include <gpxe/serial.h>
33 33
 #include "gdbmach.h"
@@ -67,20 +67,60 @@ static uint8_t gdbstub_to_hex_digit ( uint8_t b ) {
67 67
 	return ( b < 0xa ? '0' : 'a' - 0xa ) + b;
68 68
 }
69 69
 
70
-static void gdbstub_from_hex_buf ( char *dst, char *src, int len ) {
71
-	while ( len-- > 0 ) {
72
-		*dst = gdbstub_from_hex_digit ( *src++ );
73
-		if ( len-- > 0 ) {
74
-			*dst = (*dst << 4) | gdbstub_from_hex_digit ( *src++ );
70
+/*
71
+ * To make reading/writing device memory atomic, we check for
72
+ * 2- or 4-byte aligned operations and handle them specially.
73
+ */
74
+
75
+static void gdbstub_from_hex_buf ( char *dst, char *src, int lenbytes ) {
76
+	if ( lenbytes == 2 && ( ( unsigned long ) dst & 0x1 ) == 0 ) {
77
+		uint16_t i = gdbstub_from_hex_digit ( src [ 2 ] ) << 12 |
78
+			gdbstub_from_hex_digit ( src [ 3 ] ) << 8 |
79
+			gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
80
+			gdbstub_from_hex_digit ( src [ 1 ] );
81
+		* ( uint16_t * ) dst = cpu_to_le16 ( i );
82
+	} else if ( lenbytes == 4 && ( ( unsigned long ) dst & 0x3 ) == 0 ) {
83
+		uint32_t i = gdbstub_from_hex_digit ( src [ 6 ] ) << 28 |
84
+			gdbstub_from_hex_digit ( src [ 7 ] ) << 24 |
85
+			gdbstub_from_hex_digit ( src [ 4 ] ) << 20 |
86
+			gdbstub_from_hex_digit ( src [ 5 ] ) << 16 |
87
+			gdbstub_from_hex_digit ( src [ 2 ] ) << 12 |
88
+			gdbstub_from_hex_digit ( src [ 3 ] ) << 8 |
89
+			gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
90
+			gdbstub_from_hex_digit ( src [ 1 ] );
91
+		* ( uint32_t * ) dst = cpu_to_le32 ( i );
92
+	} else {
93
+		while ( lenbytes-- > 0 ) {
94
+			*dst++ = gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
95
+				gdbstub_from_hex_digit ( src [ 1 ] );
96
+			src += 2;
75 97
 		}
76
-		dst++;
77 98
 	}
78 99
 }
79 100
 
80
-static void gdbstub_to_hex_buf ( char *dst, char *src, int len ) {
81
-	while ( len-- > 0 ) {
82
-		*dst++ = gdbstub_to_hex_digit ( *src >> 4 );
83
-		*dst++ = gdbstub_to_hex_digit ( *src++ );
101
+static void gdbstub_to_hex_buf ( char *dst, char *src, int lenbytes ) {
102
+	if ( lenbytes == 2 && ( ( unsigned long ) src & 0x1 ) == 0 ) {
103
+		uint16_t i = cpu_to_le16 ( * ( uint16_t * ) src );
104
+		dst [ 0 ] = gdbstub_to_hex_digit ( i >> 4 );
105
+		dst [ 1 ] = gdbstub_to_hex_digit ( i );
106
+		dst [ 2 ] = gdbstub_to_hex_digit ( i >> 12 );
107
+		dst [ 3 ] = gdbstub_to_hex_digit ( i >> 8 );
108
+	} else if ( lenbytes == 4 && ( ( unsigned long ) src & 0x3 ) == 0 ) {
109
+		uint32_t i = cpu_to_le32 ( * ( uint32_t * ) src );
110
+		dst [ 0 ] = gdbstub_to_hex_digit ( i >> 4 );
111
+		dst [ 1 ] = gdbstub_to_hex_digit ( i );
112
+		dst [ 2 ] = gdbstub_to_hex_digit ( i >> 12 );
113
+		dst [ 3 ] = gdbstub_to_hex_digit ( i >> 8 );
114
+		dst [ 4 ] = gdbstub_to_hex_digit ( i >> 20 );
115
+		dst [ 5 ] = gdbstub_to_hex_digit ( i >> 16);
116
+		dst [ 6 ] = gdbstub_to_hex_digit ( i >> 28 );
117
+		dst [ 7 ] = gdbstub_to_hex_digit ( i >> 24 );
118
+	} else {
119
+		while ( lenbytes-- > 0 ) {
120
+			*dst++ = gdbstub_to_hex_digit ( *src >> 4 );
121
+			*dst++ = gdbstub_to_hex_digit ( *src );
122
+			src++;
123
+		}
84 124
 	}
85 125
 }
86 126
 
@@ -179,7 +219,7 @@ static void gdbstub_write_regs ( struct gdbstub *stub ) {
179 219
 		gdbstub_send_errno ( stub, POSIX_EINVAL );
180 220
 		return;
181 221
 	}
182
-	gdbstub_from_hex_buf ( ( char * ) stub->regs, &stub->payload [ 1 ], stub->len );
222
+	gdbstub_from_hex_buf ( ( char * ) stub->regs, &stub->payload [ 1 ], GDBMACH_SIZEOF_REGS );
183 223
 	gdbstub_send_ok ( stub );
184 224
 }
185 225
 
@@ -204,7 +244,7 @@ static void gdbstub_write_mem ( struct gdbstub *stub ) {
204 244
 		gdbstub_send_errno ( stub, POSIX_EINVAL );
205 245
 		return;
206 246
 	}
207
-	gdbstub_from_hex_buf ( ( char * ) args [ 0 ], &stub->payload [ colon + 1 ], stub->len - colon - 1 );
247
+	gdbstub_from_hex_buf ( ( char * ) args [ 0 ], &stub->payload [ colon + 1 ], ( stub->len - colon - 1 ) / 2 );
208 248
 	gdbstub_send_ok ( stub );
209 249
 }
210 250
 

Načítá se…
Zrušit
Uložit