// SPDX-License-Identifier: GPL-2.0 /* * Based on the same principle as kgdboe using the NETPOLL api, this * driver uses a console polling api to implement a gdb serial inteface * which is multiplexed on a console port. * * Maintainer: Jason Wessel <jason.wessel@windriver.com> * * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
*/
/* * When we leave the debug trap handler we need to reset the keyboard status * (since the original keyboard state gets partially clobbered by kdb use of * the keyboard). * * The path to deliver the reset is somewhat circuitous. * * To deliver the reset we register an input handler, reset the keyboard and * then deregister the input handler. However, to get this done right, we do * have to carefully manage the calling context because we can only register * input handlers from task context. * * In particular we need to trigger the action from the debug trap handler with * all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code * (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to * schedule a callback from a hardirq context. From there we have to defer the * work again, this time using schedule_work(), to get a callback using the * system workqueue, which runs in task context.
*/ #ifdef CONFIG_KDB_KEYBOARD staticint kgdboc_reset_connect(struct input_handler *handler, struct input_dev *dev, conststruct input_device_id *id)
{
input_reset_device(dev);
/* Return an error - we do not want to bind, just to reset */ return -ENODEV;
}
staticvoid kgdboc_reset_disconnect(struct input_handle *handle)
{ /* We do not expect anyone to actually bind to us */
BUG();
}
staticvoid kgdboc_restore_input_helper(struct work_struct *dummy)
{ /* * We need to take a mutex to prevent several instances of * this work running on different CPUs so they don't try * to register again already registered handler.
*/
mutex_lock(&kgdboc_reset_mutex);
if (input_register_handler(&kgdboc_reset_handler) == 0)
input_unregister_handler(&kgdboc_reset_handler);
p = tty_find_polling_driver(cptr, &tty_line); if (!p) goto noconfig;
/* * Take console_lock to serialize device() callback with * other console operations. For example, fg_console is * modified under console_lock when switching vt.
*/
console_lock();
cookie = console_srcu_read_lock();
for_each_console_srcu(cons) { int idx; if (cons->device && cons->device(cons, &idx) == p &&
idx == tty_line) {
kgdboc_io_ops.cons = cons; break;
}
}
console_srcu_read_unlock(cookie);
console_unlock();
kgdb_tty_driver = p;
kgdb_tty_line = tty_line;
do_register:
err = kgdb_register_io_module(&kgdboc_io_ops); if (err) goto noconfig;
/* * kgdboc is a little bit of an odd "platform_driver". It can be * up and running long before the platform_driver object is * created and thus doesn't actually store anything in it. There's * only one instance of kgdb so anything is stored as global state. * The platform_driver is only created so that we can leverage the * kernel's mechanisms (like -EPROBE_DEFER) to call us when our * underlying tty is ready. Here we init our platform driver and * then create the single kgdboc instance.
*/
ret = platform_driver_register(&kgdboc_platform_driver); if (ret) return ret;
kgdboc_pdev = platform_device_alloc("kgdboc", PLATFORM_DEVID_NONE); if (!kgdboc_pdev) {
ret = -ENOMEM; goto err_did_register;
}
ret = platform_device_add(kgdboc_pdev); if (!ret) return 0;
staticint param_set_kgdboc_var(constchar *kmessage, conststruct kernel_param *kp)
{
size_t len = strlen(kmessage); int ret = 0;
if (len >= MAX_CONFIG_LEN) {
pr_err("config string too long\n"); return -ENOSPC;
}
if (kgdb_connected) {
pr_err("Cannot reconfigure while KGDB is connected.\n"); return -EBUSY;
}
mutex_lock(&config_mutex);
strcpy(config, kmessage); /* Chop out \n char as a result of echo */ if (len && config[len - 1] == '\n')
config[len - 1] = '\0';
if (configured == 1)
cleanup_kgdboc();
/* * Configure with the new params as long as init already ran. * Note that we can get called before init if someone loads us * with "modprobe kgdboc kgdboc=..." or if they happen to use * the odd syntax of "kgdboc.kgdboc=..." on the kernel command.
*/ if (configured >= 0)
ret = configure_kgdboc();
/* * If we couldn't configure then clear out the config. Note that * specifying an invalid config on the kernel command line vs. * through sysfs have slightly different behaviors. If we fail * to configure what was specified on the kernel command line * we'll leave it in the 'config' and return -EPROBE_DEFER from * our probe. When specified through sysfs userspace is * responsible for loading the tty driver before setting up.
*/ if (ret)
config[0] = '\0';
mutex_unlock(&config_mutex);
return ret;
}
staticint dbg_restore_graphics;
staticvoid kgdboc_pre_exp_handler(void)
{ if (!dbg_restore_graphics && kgdboc_use_kms) {
dbg_restore_graphics = 1;
con_debug_enter(vc_cons[fg_console].d);
} /* Increment the module count when the debugger is active */ if (!kgdb_connected)
try_module_get(THIS_MODULE);
}
staticvoid kgdboc_post_exp_handler(void)
{ /* decrement the module count when the debugger detaches */ if (!kgdb_connected)
module_put(THIS_MODULE); if (kgdboc_use_kms && dbg_restore_graphics) {
dbg_restore_graphics = 0;
con_debug_leave();
}
kgdboc_restore_input();
}
#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) staticint kgdboc_option_setup(char *opt)
{ if (!opt) {
pr_err("config string not provided\n"); return 1;
}
if (strlen(opt) >= MAX_CONFIG_LEN) {
pr_err("config string too long\n"); return 1;
}
strcpy(config, opt);
return 1;
}
__setup("kgdboc=", kgdboc_option_setup);
/* This is only available if kgdboc is a built in for early debugging */ staticint __init kgdboc_early_init(char *opt)
{
kgdboc_option_setup(opt);
configure_kgdboc(); return 0;
}
staticvoid kgdboc_earlycon_pre_exp_handler(void)
{ struct console *con; staticbool already_warned; int cookie;
if (already_warned) return;
/* * When the first normal console comes up the kernel will take all * the boot consoles out of the list. Really, we should stop using * the boot console when it does that but until a TTY is registered * we have no other choice so we keep using it. Since not all * serial drivers might be OK with this, print a warning once per * boot if we detect this case.
*/
cookie = console_srcu_read_lock();
for_each_console_srcu(con) { if (con == kgdboc_earlycon_io_ops.cons) break;
}
console_srcu_read_unlock(cookie); if (con) return;
already_warned = true;
pr_warn("kgdboc_earlycon is still using bootconsole\n");
}
staticint kgdboc_earlycon_deferred_exit(struct console *con)
{ /* * If we get here it means the boot console is going away but we * don't yet have a suitable replacement. Don't pass through to * the original exit routine. We'll call it later in our deinit() * function. For now, restore the original exit() function pointer * as a sentinal that we've hit this point.
*/
con->exit = earlycon_orig_exit;
return 0;
}
staticvoid kgdboc_earlycon_deinit(void)
{ if (!kgdboc_earlycon_io_ops.cons) return;
if (kgdboc_earlycon_io_ops.cons->exit == kgdboc_earlycon_deferred_exit) /* * kgdboc_earlycon is exiting but original boot console exit * was never called (AKA kgdboc_earlycon_deferred_exit() * didn't ever run). Undo our trap.
*/
kgdboc_earlycon_io_ops.cons->exit = earlycon_orig_exit; elseif (kgdboc_earlycon_io_ops.cons->exit) /* * We skipped calling the exit() routine so we could try to * keep using the boot console even after it went away. We're * finally done so call the function now.
*/
kgdboc_earlycon_io_ops.cons->exit(kgdboc_earlycon_io_ops.cons);
/* * Look for a matching console, or if the name was left blank just * pick the first one we find.
*/
/* * Hold the console_list_lock to guarantee that no consoles are * unregistered until the kgdboc_earlycon setup is complete. * Trapping the exit() callback relies on exit() not being * called until the trap is setup. This also allows safe * traversal of the console list and race-free reading of @flags.
*/
console_list_lock();
for_each_console(con) { if (con->write && con->read &&
(con->flags & (CON_BOOT | CON_ENABLED)) &&
(!opt || !opt[0] || strcmp(con->name, opt) == 0)) break;
}
if (!con) { /* * Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets * in first and, in any case, on ACPI systems earlycon may * defer its own initialization (usually to somewhere within * setup_arch() ). To cope with either of these situations * we can defer our own initialization to a little later in * the boot.
*/ if (!kgdboc_earlycon_late_enable) {
pr_info("No suitable earlycon yet, will try later\n"); if (opt)
strscpy(kgdboc_earlycon_param, opt, sizeof(kgdboc_earlycon_param));
kgdboc_earlycon_late_enable = true;
} else {
pr_info("Couldn't find kgdb earlycon\n");
} goto unlock;
}
kgdboc_earlycon_io_ops.cons = con;
pr_info("Going to register kgdb with earlycon '%s'\n", con->name); if (kgdb_register_io_module(&kgdboc_earlycon_io_ops) != 0) {
kgdboc_earlycon_io_ops.cons = NULL;
pr_info("Failed to register kgdb with earlycon\n");
} else { /* Trap exit so we can keep earlycon longer if needed. */
earlycon_orig_exit = con->exit;
con->exit = kgdboc_earlycon_deferred_exit;
}
unlock:
console_list_unlock();
/* Non-zero means malformed option so we always return zero */ return 0;
}
/* * This is only intended for the late adoption of an early console. * * It is not a reliable way to adopt regular consoles because we can not * control what order console initcalls are made and, in any case, many * regular consoles are registered much later in the boot process than * the console initcalls!
*/ staticint __init kgdboc_earlycon_late_init(void)
{ if (kgdboc_earlycon_late_enable)
kgdboc_earlycon_init(kgdboc_earlycon_param); return 0;
}
console_initcall(kgdboc_earlycon_late_init);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.