38
38
import typing
39
39
from abc import abstractmethod
40
40
from pathlib import Path
41
+ from threading import Thread
41
42
from typing import Optional
42
43
43
44
_cheribuild_root = Path (__file__ ).resolve ().parent
@@ -268,6 +269,16 @@ def __init__(self, gdb: pexpect.spawn, openocd: pexpect.spawn, serial: SerialCon
268
269
self .serial = serial
269
270
270
271
272
+ class BackgroundExpectEOF (Thread ):
273
+ def __init__ (self , child ):
274
+ Thread .__init__ (self )
275
+ self .child = child
276
+ self .daemon = True
277
+
278
+ def run (self ):
279
+ self .child .expect (pexpect .EOF , timeout = None )
280
+
281
+
271
282
def reset_soc (conn : FpgaConnection ):
272
283
# On the rare occasion you need to reset SoC stuff not just the core, set *(0x6fff0000)=1 does a write to a GPIO
273
284
# block whose output is connected to the SoC's reset so that lets you reset the whole SoC
@@ -327,12 +338,26 @@ def load_and_start_kernel(
327
338
gdb_start_time = datetime .datetime .utcnow ()
328
339
openocd , openocd_gdb_port = start_openocd (openocd_cmd , num_cores )
329
340
# openocd is running, now start GDB
330
- args = [str (Path (bios_image ).absolute ()), "-ex" , "target extended-remote :" + str (openocd_gdb_port )]
341
+ # NB: Cannot set the actual file since GDB will then expect OpenOCD's
342
+ # gdbserver to provide capabilities and fail to read the PC (PCC).
343
+ args = ["-ex" , "set architecture riscv" ]
344
+ # NB: Avoids software single stepping as writing ebreak to the bootrom
345
+ # doesn't work (silently fails at least with Toooba at time of writing).
346
+ args += ["-ex" , "set os none" ]
347
+ args += ["-ex" , "symbol-file " + str (Path (bios_image ).absolute ())]
348
+ args += ["-ex" , "target extended-remote :" + str (openocd_gdb_port )]
331
349
args += ["-ex" , "set confirm off" ] # avoid interactive prompts
332
350
args += ["-ex" , "set pagination off" ] # avoid paginating output, requiring input
333
351
args += ["-ex" , "set style enabled off" ] # disable colours since they break the matcher strings
334
352
args += ["-ex" , "monitor reset init" ] # reset and go back to boot room
353
+ if num_cores > 1 :
354
+ args += ["-ex" , "thread 1" ] # ensure we're on core 0
335
355
args += ["-ex" , "si 5" ] # we need to run the first few instructions to get a valid DTB
356
+ if num_cores > 1 :
357
+ for core in range (1 , num_cores ):
358
+ args += ["-ex" , f"thread { core + 1 :d} " ] # switch to thread (core + 1) (GDB counts from 1)
359
+ args += ["-ex" , "si 5" ] # execute bootrom on every other core
360
+ args += ["-ex" , "thread 1" ] # switch back to core 0
336
361
args += ["-ex" , "set disassemble-next-line on" ]
337
362
# Load the kernel image first since load changes the next PC to the entry point
338
363
if kernel_image is not None :
@@ -351,8 +376,6 @@ def load_and_start_kernel(
351
376
if num_cores > 1 :
352
377
args += ["-ex" , "set $entry_point = $pc" ] # Record the entry point to the bios
353
378
for core in range (1 , num_cores ):
354
- args += ["-ex" , f"thread { core + 1 :d} " ] # switch to thread (core + 1) (GDB counts from 1)
355
- args += ["-ex" , "si 5" ] # execute bootrom on every other core
356
379
args += ["-ex" , "set $pc=$entry_point" ] # set every other core to the start of the bios
357
380
args += ["-ex" , "thread 1" ] # switch back to core 0
358
381
if extra_gdb_commands is not None :
@@ -368,6 +391,9 @@ def load_and_start_kernel(
368
391
# openOCD should acknowledge the GDB connection:
369
392
openocd .expect_exact ([f"Info : accepting 'gdb' connection on tcp/{ openocd_gdb_port } " ])
370
393
success ("openocd accepted GDB connection" )
394
+ # Now we're done with OpenOCD and want to ensure anything it logs doesn't
395
+ # lead to backpressure and block it
396
+ BackgroundExpectEOF (openocd ).start ()
371
397
gdb .expect_exact (["Remote debugging using :" + str (openocd_gdb_port )])
372
398
success ("GDB connected to openocd" )
373
399
# XXX: doesn't match with recent GDB: gdb.expect_exact(["0x0000000070000000 in ??"])
@@ -376,6 +402,10 @@ def load_and_start_kernel(
376
402
# XXX: doesn't match with recent GDB: gdb.expect_exact(["0x0000000044000000 in ??"])
377
403
gdb .expect_exact (["0x0000000044000000" ])
378
404
success ("Done executing bootrom" )
405
+ if num_cores > 1 :
406
+ for core in range (1 , num_cores ):
407
+ gdb .expect_exact (["0x0000000044000000" ])
408
+ success ("Done executing bootrom on all other cores" )
379
409
if kernel_image is not None :
380
410
gdb .expect_exact (["Loading section .text" ])
381
411
load_start_time = datetime .datetime .utcnow ()
@@ -391,10 +421,6 @@ def load_and_start_kernel(
391
421
load_end_time = datetime .datetime .utcnow ()
392
422
success ("Finished loading bootloader image in " , load_end_time - load_start_time )
393
423
gdb_finish_time = load_end_time
394
- if num_cores > 1 :
395
- for core in range (1 , num_cores ):
396
- gdb .expect_exact (["0x0000000044000000" ])
397
- success ("Done executing bootrom on all other cores" )
398
424
gdb .expect_exact (["ready to continue" ])
399
425
gdb .sendline ("continue" )
400
426
success ("Starting CheriBSD after " , datetime .datetime .utcnow () - gdb_start_time )
0 commit comments