37
37
static int riscv_semihosting_setup (struct target * target , int enable );
38
38
static int riscv_semihosting_post_result (struct target * target );
39
39
40
+ static int riscv_semihosting_detect_magic_sequence (struct target * target ,
41
+ const target_addr_t pc , bool * sequence_found )
42
+ {
43
+ assert (sequence_found );
44
+
45
+ /* The semihosting "magic" sequence must be the exact three instructions
46
+ * listed below. All these instructions, including the ebreak, must be
47
+ * uncompressed (4 bytes long). */
48
+ const uint32_t magic [] = {
49
+ 0x01f01013 , /* slli zero,zero,0x1f */
50
+ 0x00100073 , /* ebreak */
51
+ 0x40705013 /* srai zero,zero,0x7 */
52
+ };
53
+
54
+ LOG_TARGET_DEBUG (target , "Checking for RISC-V semihosting sequence "
55
+ "at PC = 0x%" TARGET_PRIxADDR , pc );
56
+
57
+ /* Read three uncompressed instructions:
58
+ * The previous, the current one (pointed to by PC) and the next one. */
59
+ const target_addr_t sequence_start_address = pc - 4 ;
60
+ for (int i = 0 ; i < 3 ; i ++ ) {
61
+ uint8_t buf [4 ];
62
+
63
+ /* Instruction memories may not support arbitrary read size.
64
+ * Use any size that will work. */
65
+ const target_addr_t address = sequence_start_address + (4 * i );
66
+ int result = riscv_read_by_any_size (target , address , 4 , buf );
67
+ if (result != ERROR_OK ) {
68
+ * sequence_found = false;
69
+ return result ;
70
+ }
71
+
72
+ /* RISC-V instruction layout in memory is always little endian,
73
+ * regardless of the endianness of the whole system. */
74
+ const uint32_t value = le_to_h_u32 (buf );
75
+
76
+ LOG_TARGET_DEBUG (target , "compare 0x%08" PRIx32 " from 0x%" PRIx64 " against 0x%08" PRIx32 ,
77
+ value , address , magic [i ]);
78
+ if (value != magic [i ]) {
79
+ LOG_TARGET_DEBUG (target , "Not a RISC-V semihosting sequence" );
80
+ * sequence_found = false;
81
+ return ERROR_OK ;
82
+ }
83
+ }
84
+
85
+ LOG_TARGET_DEBUG (target , "RISC-V semihosting sequence found "
86
+ "at PC = 0x%" TARGET_PRIxADDR , pc );
87
+ * sequence_found = true;
88
+ return ERROR_OK ;
89
+ }
90
+
40
91
/**
41
92
* Initialize RISC-V semihosting. Use common ARM code.
42
93
*/
@@ -60,42 +111,32 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
60
111
assert (semihosting );
61
112
62
113
if (!semihosting -> is_active ) {
63
- LOG_TARGET_DEBUG (target , " -> NONE (! semihosting->is_active )" );
114
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (semihosting not enabled )" );
64
115
return SEMIHOSTING_NONE ;
65
116
}
66
117
67
118
riscv_reg_t pc ;
68
119
int result = riscv_reg_get (target , & pc , GDB_REGNO_PC );
69
- if (result != ERROR_OK )
120
+ if (result != ERROR_OK ) {
121
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read PC)" );
70
122
return SEMIHOSTING_ERROR ;
123
+ }
71
124
72
- /*
73
- * The instructions that trigger a semihosting call,
74
- * always uncompressed, should look like:
75
- */
76
- uint32_t magic [] = {
77
- 0x01f01013 , /* slli zero,zero,0x1f */
78
- 0x00100073 , /* ebreak */
79
- 0x40705013 /* srai zero,zero,0x7 */
80
- };
125
+ bool sequence_found ;
126
+ * retval = riscv_semihosting_detect_magic_sequence (target , pc , & sequence_found );
127
+ if (* retval != ERROR_OK ) {
128
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (during magic seq. detection)" );
129
+ return SEMIHOSTING_ERROR ;
130
+ }
81
131
82
- /* Read three uncompressed instructions: The previous, the current one (pointed to by PC) and the next one */
83
- for (int i = 0 ; i < 3 ; i ++ ) {
84
- uint8_t buf [4 ];
85
- /* Instruction memories may not support arbitrary read size. Use any size that will work. */
86
- target_addr_t address = (pc - 4 ) + 4 * i ;
87
- * retval = riscv_read_by_any_size (target , address , 4 , buf );
88
- if (* retval != ERROR_OK )
89
- return SEMIHOSTING_ERROR ;
90
- uint32_t value = target_buffer_get_u32 (target , buf );
91
- LOG_TARGET_DEBUG (target , "compare 0x%08x from 0x%" PRIx64 " against 0x%08x" ,
92
- value , address , magic [i ]);
93
- if (value != magic [i ]) {
94
- LOG_TARGET_DEBUG (target , " -> NONE (no magic)" );
95
- return SEMIHOSTING_NONE ;
96
- }
132
+ if (!sequence_found ) {
133
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (no magic sequence)" );
134
+ return SEMIHOSTING_NONE ;
97
135
}
98
136
137
+ /* Otherwise we have a semihosting call (and semihosting is enabled).
138
+ * Proceed with the semihosting. */
139
+
99
140
/*
100
141
* Perform semihosting call if we are not waiting on a fileio
101
142
* operation to complete.
@@ -108,12 +149,14 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
108
149
result = riscv_reg_get (target , & r0 , GDB_REGNO_A0 );
109
150
if (result != ERROR_OK ) {
110
151
LOG_TARGET_ERROR (target , "Could not read semihosting operation code (register a0)" );
152
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read a0)" );
111
153
return SEMIHOSTING_ERROR ;
112
154
}
113
155
114
156
result = riscv_reg_get (target , & r1 , GDB_REGNO_A1 );
115
157
if (result != ERROR_OK ) {
116
158
LOG_TARGET_ERROR (target , "Could not read semihosting operation code (register a1)" );
159
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read a1)" );
117
160
return SEMIHOSTING_ERROR ;
118
161
}
119
162
@@ -128,11 +171,13 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
128
171
* retval = semihosting_common (target );
129
172
if (* retval != ERROR_OK ) {
130
173
LOG_TARGET_ERROR (target , "Failed semihosting operation (0x%02X)" , semihosting -> op );
174
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (error during semihosting processing)" );
131
175
return SEMIHOSTING_ERROR ;
132
176
}
133
177
} else {
134
178
/* Unknown operation number, not a semihosting call. */
135
179
LOG_TARGET_ERROR (target , "Unknown semihosting operation requested (op = 0x%x)" , semihosting -> op );
180
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (unknown semihosting opcode)" );
136
181
return SEMIHOSTING_NONE ;
137
182
}
138
183
}
@@ -147,11 +192,11 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
147
192
* operation to complete.
148
193
*/
149
194
if (semihosting -> is_resumable && !semihosting -> hit_fileio ) {
150
- LOG_TARGET_DEBUG (target , " -> HANDLED" );
195
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: HANDLED" );
151
196
return SEMIHOSTING_HANDLED ;
152
197
}
153
198
154
- LOG_TARGET_DEBUG (target , " -> WAITING" );
199
+ LOG_TARGET_DEBUG (target , "Semihosting outcome: WAITING" );
155
200
return SEMIHOSTING_WAITING ;
156
201
}
157
202
0 commit comments