mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
console: make awesome
This commit is contained in:
64
README.adoc
64
README.adoc
@@ -1832,34 +1832,68 @@ It is useless with QEMU since we already have full system visibility with `-gdb`
|
||||
|
||||
Cheaper than JTAG (free) and easier to setup (all you need is serial), but with less visibility as it depends on the kernel working, so e.g.: dies on panic, does not see boot sequence.
|
||||
|
||||
Usage:
|
||||
First run the kernel with:
|
||||
|
||||
....
|
||||
./run --kgdb
|
||||
./run-gdb --kgdb
|
||||
....
|
||||
|
||||
In GDB:
|
||||
this passes the following options on the kernel CLI:
|
||||
|
||||
....
|
||||
c
|
||||
kgdbwait kgdboc=ttyS1,115200
|
||||
....
|
||||
|
||||
In QEMU:
|
||||
`kgdbwait` tells the kernel to wait for KGDB to connect.
|
||||
|
||||
So the kernel sets things up enough for KGDB to start working, and then boot pauses waiting for connection:
|
||||
|
||||
....
|
||||
<6>[ 4.866050] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
|
||||
<6>[ 4.893205] 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
|
||||
<6>[ 4.916271] 00:06: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
|
||||
<6>[ 4.987771] KGDB: Registered I/O driver kgdboc
|
||||
<2>[ 4.996053] KGDB: Waiting for connection from remote gdb...
|
||||
|
||||
Entering kdb (current=0x(____ptrval____), pid 1) on processor 0 due to Keyboard Entry
|
||||
[0]kdb>
|
||||
....
|
||||
|
||||
KGDB expects the connection at `ttyS1`, our second serial port after `ttyS0` which contains the terminal.
|
||||
|
||||
So now we can connect to the serial port with GDB:
|
||||
|
||||
....
|
||||
./run-gdb --kgdb --no-continue
|
||||
....
|
||||
|
||||
Once GDB connects, it is left inside the function `kgdb_breakpoint`.
|
||||
|
||||
So now we can set breakpoints and continue as usual.
|
||||
|
||||
For example, in GDB:
|
||||
|
||||
....
|
||||
continue
|
||||
....
|
||||
|
||||
Then in QEMU:
|
||||
|
||||
....
|
||||
/count.sh &
|
||||
/kgdb.sh
|
||||
....
|
||||
|
||||
In GDB:
|
||||
link:rootfs_overlay:kgdb.sh[] pauses the kernel for KGDB, and gives control back to GDB.
|
||||
|
||||
And now in GDB we do the usual:
|
||||
|
||||
....
|
||||
b __x64_sys_write
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
break __x64_sys_write
|
||||
continue
|
||||
continue
|
||||
continue
|
||||
continue
|
||||
....
|
||||
|
||||
And now you can count from GDB!
|
||||
@@ -1873,9 +1907,11 @@ See also:
|
||||
|
||||
=== KGDB ARM
|
||||
|
||||
GDB not connecting to KGDB in ARM. Possibly linked to `-serial stdio`. See also: https://stackoverflow.com/questions/14155577/how-to-use-kgdb-on-arm
|
||||
GDB not connecting to KGDB in `arm` and `aarch64`.
|
||||
|
||||
Main shell just falls on:
|
||||
Main question: https://stackoverflow.com/questions/14155577/how-to-use-kgdb-on-arm
|
||||
|
||||
The main console just hangs on:
|
||||
|
||||
....
|
||||
Entering kdb (current=0xf8ce07d3, pid 1) due to Keyboard Entry
|
||||
@@ -1893,6 +1929,8 @@ Ignoring packet error, continuing...
|
||||
Remote replied unexpectedly to 'vMustReplyEmpty': timeout
|
||||
....
|
||||
|
||||
I wanted to try to and run run KGDB on a second serial to see if it makes a difference, but QEMU `-M virt` does not seem to support it: https://stackoverflow.com/questions/53080745/can-qemu-m-virt-on-arm-aarch64-have-multiple-serial-ttys-like-such-as-pl011-t
|
||||
|
||||
=== KGDB kernel modules
|
||||
|
||||
In QEMU:
|
||||
|
||||
@@ -670,6 +670,7 @@ def setup(parser):
|
||||
args.gem5_build_id = args.gem5_worktree
|
||||
this_module.machine = args.machine
|
||||
this_module.setup_dry_run_arguments(args)
|
||||
this_module.is_arm = False
|
||||
if args.arch == 'arm':
|
||||
this_module.armv = 7
|
||||
this_module.gem5_arch = 'ARM'
|
||||
@@ -683,6 +684,7 @@ def setup(parser):
|
||||
else:
|
||||
if this_module.machine is None:
|
||||
this_module.machine = 'virt'
|
||||
this_module.is_arm = True
|
||||
elif args.arch == 'aarch64':
|
||||
this_module.armv = 8
|
||||
this_module.gem5_arch = 'ARM'
|
||||
@@ -696,6 +698,7 @@ def setup(parser):
|
||||
else:
|
||||
if this_module.machine is None:
|
||||
this_module.machine = 'virt'
|
||||
this_module.is_arm = True
|
||||
elif args.arch == 'x86_64':
|
||||
this_module.crosstool_ng_toolchain_prefix = 'x86_64-unknown-elf'
|
||||
this_module.gem5_arch = 'X86'
|
||||
|
||||
@@ -117,6 +117,7 @@ scons \
|
||||
if "$baremetal"; then
|
||||
pkgs="${pkgs} \
|
||||
docbook2x \
|
||||
libtool-bin \
|
||||
"
|
||||
fi
|
||||
command -v apt-get >/dev/null 2>&1 || {
|
||||
|
||||
31
run
31
run
@@ -81,11 +81,22 @@ def main(args, extra_args=None):
|
||||
kernel_cli += ' {}=/eval_base64.sh'.format(initarg)
|
||||
kernel_cli_after_dash += ' lkmc_eval="{}"'.format(common.base64_encode(args.eval))
|
||||
if not args.graphic:
|
||||
if args.arch == 'x86_64':
|
||||
kernel_cli += ' console=ttyS0'
|
||||
else:
|
||||
kernel_cli += ' console=ttyAMA0'
|
||||
extra_qemu_args.append('-nographic')
|
||||
console = None
|
||||
console_type = None
|
||||
console_count = 0
|
||||
if args.arch == 'x86_64':
|
||||
console_type = 'ttyS'
|
||||
elif common.is_arm:
|
||||
console_type = 'ttyAMA'
|
||||
console = '{}{}'.format(console_type, console_count)
|
||||
if not (args.arch == 'x86_64' and args.graphic):
|
||||
console_count += 1
|
||||
kernel_cli += ' console={}'.format(console)
|
||||
extra_console = '{}{}'.format(console_type, console_count)
|
||||
console_count += 1
|
||||
if args.kgdb:
|
||||
kernel_cli += ' kgdboc={},115200'.format(console)
|
||||
if kernel_cli_after_dash:
|
||||
kernel_cli += " -{}".format(kernel_cli_after_dash)
|
||||
extra_env = {}
|
||||
@@ -161,12 +172,12 @@ def main(args, extra_args=None):
|
||||
if args.arch == 'x86_64':
|
||||
if args.kvm:
|
||||
cmd.extend(['--cpu-type', 'X86KvmCPU'])
|
||||
cmd.extend(['--command-line', 'earlyprintk=ttyS0 lpj=7999923 root=/dev/sda {}'.format(kernel_cli)])
|
||||
elif args.arch == 'arm' or args.arch == 'aarch64':
|
||||
cmd.extend(['--command-line', 'earlyprintk={} lpj=7999923 root=/dev/sda {}'.format(console, kernel_cli)])
|
||||
elif common.is_arm:
|
||||
# TODO why is it mandatory to pass mem= here? Not true for QEMU.
|
||||
# Anything smaller than physical blows up as expected, but why can't it auto-detect the right value?
|
||||
cmd.extend([
|
||||
'--command-line', 'earlyprintk=pl011,0x1c090000 console=ttyAMA0 lpj=19988480 rw loglevel=8 mem={} root=/dev/sda {}'.format(memory, kernel_cli),
|
||||
'--command-line', 'earlyprintk=pl011,0x1c090000 lpj=19988480 rw loglevel=8 mem={} root=/dev/sda {}'.format(memory, kernel_cli),
|
||||
'--dtb-filename', os.path.join(common.gem5_system_dir, 'arm', 'dt', 'armv{}_gem5_v1_{}cpu.dtb'.format(common.armv, args.cpus)),
|
||||
'--machine-type', common.machine,
|
||||
'--param', 'system.panic_on_panic = True',
|
||||
@@ -295,17 +306,13 @@ def main(args, extra_args=None):
|
||||
else:
|
||||
virtio_gpu_pci = ['-device', 'virtio-gpu-pci']
|
||||
if args.arch == 'x86_64':
|
||||
if args.kgdb:
|
||||
kernel_cli += ' kgdboc=ttyS1,115200'
|
||||
append = ['-append', '{} nopat {}'.format(root, kernel_cli)]
|
||||
cmd.extend([
|
||||
'-M', common.machine,
|
||||
'-device', 'edu',
|
||||
])
|
||||
elif args.arch == 'arm' or args.arch == 'aarch64':
|
||||
elif common.is_arm:
|
||||
extra_emulator_args.append('-semihosting')
|
||||
if args.kgdb:
|
||||
kernel_cli += ' kgdboc=ttyAMA0,115200'
|
||||
if args.arch == 'arm':
|
||||
cpu = 'cortex-a15'
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user