From ad077d3943f79c0f6481dab929970613c33c31a7 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Sun, 14 May 2017 13:49:15 +0100 Subject: [PATCH] Workqueue works! QEMU CLI mode with -n for panic --- README.md | 4 ++++ kernel_module/workqueue_cheat.c | 11 ++++++++--- rootfs_overlay/workqueue_cheat.sh | 9 +++++++++ run | 22 +++++++++++++++++++++- 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100755 rootfs_overlay/workqueue_cheat.sh diff --git a/README.md b/README.md index 8341064..3c24bc5 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ We use `printk` a lot, and it shows on the QEMU terminal by default. If that ann See also: +When your kernel starts crashing, get the full trace with: + + ./run -n + 1. [Introduction](introduction.md) 1. [Build](build.md) 1. [kmod](kmod.md) diff --git a/kernel_module/workqueue_cheat.c b/kernel_module/workqueue_cheat.c index ed33397..30ce613 100644 --- a/kernel_module/workqueue_cheat.c +++ b/kernel_module/workqueue_cheat.c @@ -7,7 +7,7 @@ Usage: Creates a separate thread. So init_module can return, but some work will still get done. -TODO why can't call this workqueue.ko? +Can't call this just workqueue.c because there is already a built-in with that name: https://unix.stackexchange.com/questions/364956/how-can-insmod-fail-with-kernel-module-is-already-loaded-even-is-lsmod-does-not */ @@ -19,14 +19,15 @@ MODULE_LICENSE("GPL"); static struct workqueue_struct *queue; -static void worker_func(struct work_struct *work) +static void work_func(struct work_struct *work) { printk(KERN_INFO "worker\n"); } +DECLARE_WORK(work, work_func); + int init_module(void) { - DECLARE_WORK(work, worker_func); queue = create_singlethread_workqueue("myworkqueue"); queue_work(queue, &work); return 0; @@ -34,5 +35,9 @@ int init_module(void) void cleanup_module(void) { + /* TODO why is this needed? Why flush_workqueue doesn't work? (re-insmod panics) + * http://stackoverflow.com/questions/37216038/whats-the-difference-between-flush-delayed-work-and-cancel-delayed-work-sync */ + /*flush_workqueue(queue);*/ + cancel_work_sync(&work); destroy_workqueue(queue); } diff --git a/rootfs_overlay/workqueue_cheat.sh b/rootfs_overlay/workqueue_cheat.sh new file mode 100755 index 0000000..950cbf7 --- /dev/null +++ b/rootfs_overlay/workqueue_cheat.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Got a few kernel crashes after insert / remove, so let's do this a few times. +insmod /workqueue_cheat.ko +rmmod workqueue_cheat +insmod /workqueue_cheat.ko +rmmod workqueue_cheat +insmod /workqueue_cheat.ko +rmmod workqueue_cheat diff --git a/run b/run index 84a8344..dbc2b1f 100755 --- a/run +++ b/run @@ -1,5 +1,24 @@ #!/usr/bin/env bash set -e + +# CLI handling. +nographic=false +while getopts n OPT; do + case "$OPT" in + n) + nographic=true + ;; + esac +done +if $nographic; then + extra_append='console=ttyS0' + extra_flags='-nographic' +else + extra_append='' + extra_flags='' +fi + +# Work. cd buildroot make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig echo ' @@ -11,9 +30,10 @@ BR2_ROOTFS_OVERLAY="../rootfs_overlay" env -u LD_LIBRARY_PATH make BR2_JLEVEL="$(($(nproc) - 2))" kernel_module-rebuild all qemu-system-x86_64 \ -M pc \ - -append 'root=/dev/vda' \ + -append "root=/dev/vda $extra_append" \ -drive file=output/images/rootfs.ext2,if=virtio,format=raw \ -kernel output/images/bzImage \ -net nic,model=virtio \ -net user \ + $extra_flags \ ;