12
12
#define DBGBCR_EXEC (0x0 << 3)
13
13
#define DBGBCR_EL1 (0x1 << 1)
14
14
#define DBGBCR_E (0x1 << 0)
15
+ #define DBGBCR_LBN_SHIFT 16
16
+ #define DBGBCR_BT_SHIFT 20
17
+ #define DBGBCR_BT_ADDR_LINK_CTX (0x1 << DBGBCR_BT_SHIFT)
18
+ #define DBGBCR_BT_CTX_LINK (0x3 << DBGBCR_BT_SHIFT)
15
19
16
20
#define DBGWCR_LEN8 (0xff << 5)
17
21
#define DBGWCR_RD (0x1 << 3)
22
26
#define SPSR_D (1 << 9)
23
27
#define SPSR_SS (1 << 21)
24
28
25
- extern unsigned char sw_bp , sw_bp2 , hw_bp , hw_bp2 , bp_svc , bp_brk , hw_wp , ss_start ;
29
+ extern unsigned char sw_bp , sw_bp2 , hw_bp , hw_bp2 , bp_svc , bp_brk , hw_wp , ss_start , hw_bp_ctx ;
26
30
extern unsigned char iter_ss_begin , iter_ss_end ;
27
31
static volatile uint64_t sw_bp_addr , hw_bp_addr ;
28
32
static volatile uint64_t wp_addr , wp_data_addr ;
@@ -105,6 +109,7 @@ static void reset_debug_state(void)
105
109
isb ();
106
110
107
111
write_sysreg (0 , mdscr_el1 );
112
+ write_sysreg (0 , contextidr_el1 );
108
113
109
114
/* Reset all bcr/bvr/wcr/wvr registers */
110
115
dfr0 = read_sysreg (id_aa64dfr0_el1 );
@@ -166,6 +171,31 @@ static void install_hw_bp(uint8_t bpn, uint64_t addr)
166
171
enable_monitor_debug_exceptions ();
167
172
}
168
173
174
+ void install_hw_bp_ctx (uint8_t addr_bp , uint8_t ctx_bp , uint64_t addr ,
175
+ uint64_t ctx )
176
+ {
177
+ uint32_t addr_bcr , ctx_bcr ;
178
+
179
+ /* Setup a context-aware breakpoint for Linked Context ID Match */
180
+ ctx_bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E |
181
+ DBGBCR_BT_CTX_LINK ;
182
+ write_dbgbcr (ctx_bp , ctx_bcr );
183
+ write_dbgbvr (ctx_bp , ctx );
184
+
185
+ /*
186
+ * Setup a normal breakpoint for Linked Address Match, and link it
187
+ * to the context-aware breakpoint.
188
+ */
189
+ addr_bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E |
190
+ DBGBCR_BT_ADDR_LINK_CTX |
191
+ ((uint32_t )ctx_bp << DBGBCR_LBN_SHIFT );
192
+ write_dbgbcr (addr_bp , addr_bcr );
193
+ write_dbgbvr (addr_bp , addr );
194
+ isb ();
195
+
196
+ enable_monitor_debug_exceptions ();
197
+ }
198
+
169
199
static void install_ss (void )
170
200
{
171
201
uint32_t mdscr ;
@@ -179,8 +209,10 @@ static void install_ss(void)
179
209
180
210
static volatile char write_data ;
181
211
182
- static void guest_code (uint8_t bpn , uint8_t wpn )
212
+ static void guest_code (uint8_t bpn , uint8_t wpn , uint8_t ctx_bpn )
183
213
{
214
+ uint64_t ctx = 0xabcdef ; /* a random context number */
215
+
184
216
/* Software-breakpoint */
185
217
reset_debug_state ();
186
218
asm volatile ("sw_bp: brk #0" );
@@ -263,6 +295,17 @@ static void guest_code(uint8_t bpn, uint8_t wpn)
263
295
: : : "x0" );
264
296
GUEST_ASSERT_EQ (ss_addr [0 ], 0 );
265
297
298
+ /* Linked hardware-breakpoint */
299
+ hw_bp_addr = 0 ;
300
+ reset_debug_state ();
301
+ install_hw_bp_ctx (bpn , ctx_bpn , PC (hw_bp_ctx ), ctx );
302
+ /* Set context id */
303
+ write_sysreg (ctx , contextidr_el1 );
304
+ isb ();
305
+ asm volatile ("hw_bp_ctx: nop" );
306
+ write_sysreg (0 , contextidr_el1 );
307
+ GUEST_ASSERT_EQ (hw_bp_addr , PC (hw_bp_ctx ));
308
+
266
309
GUEST_DONE ();
267
310
}
268
311
@@ -342,11 +385,12 @@ static int debug_version(uint64_t id_aa64dfr0)
342
385
return FIELD_GET (ARM64_FEATURE_MASK (ID_AA64DFR0_DEBUGVER ), id_aa64dfr0 );
343
386
}
344
387
345
- static void test_guest_debug_exceptions (void )
388
+ static void test_guest_debug_exceptions (uint64_t aa64dfr0 )
346
389
{
347
390
struct kvm_vcpu * vcpu ;
348
391
struct kvm_vm * vm ;
349
392
struct ucall uc ;
393
+ uint8_t brp_num ;
350
394
351
395
vm = vm_create_with_one_vcpu (& vcpu , guest_code );
352
396
ucall_init (vm , NULL );
@@ -365,8 +409,15 @@ static void test_guest_debug_exceptions(void)
365
409
vm_install_sync_handler (vm , VECTOR_SYNC_CURRENT ,
366
410
ESR_EC_SVC64 , guest_svc_handler );
367
411
368
- /* Run tests with breakpoint#0 and watchpoint#0. */
369
- vcpu_args_set (vcpu , 2 , 0 , 0 );
412
+ /* Number of breakpoints */
413
+ brp_num = FIELD_GET (ARM64_FEATURE_MASK (ID_AA64DFR0_BRPS ), aa64dfr0 ) + 1 ;
414
+ __TEST_REQUIRE (brp_num >= 2 , "At least two breakpoints are required" );
415
+
416
+ /*
417
+ * Run tests with breakpoint#0, watchpoint#0, and the higiest
418
+ * numbered (context-aware) breakpoint.
419
+ */
420
+ vcpu_args_set (vcpu , 3 , 0 , 0 , brp_num - 1 );
370
421
371
422
vcpu_run (vcpu );
372
423
switch (get_ucall (vcpu , & uc )) {
@@ -483,7 +534,7 @@ int main(int argc, char *argv[])
483
534
}
484
535
}
485
536
486
- test_guest_debug_exceptions ();
537
+ test_guest_debug_exceptions (aa64dfr0 );
487
538
test_single_step_from_userspace (ss_iteration );
488
539
489
540
return 0 ;
0 commit comments