linux/drivers/tty/serial/kgdboc.c

// 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 <[email protected]>
 *
 * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
 */

#define pr_fmt(fmt)

#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/vt_kern.h>
#include <linux/input.h>
#include <linux/irq_work.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>

#define MAX_CONFIG_LEN

static struct kgdb_io		kgdboc_io_ops;

/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
static int configured		=;
static DEFINE_MUTEX(config_mutex);

static char config[MAX_CONFIG_LEN];
static struct kparam_string kps =;

static int kgdboc_use_kms;  /* 1 if we use kernel mode switching */
static struct tty_driver	*kgdb_tty_driver;
static int			kgdb_tty_line;

static struct platform_device *kgdboc_pdev;

#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE)
static struct kgdb_io		kgdboc_earlycon_io_ops;
static int                      (*earlycon_orig_exit)(struct console *con);
#endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */

/*
 * 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
static int kgdboc_reset_connect(struct input_handler *handler,
				struct input_dev *dev,
				const struct input_device_id *id)
{}

static void kgdboc_reset_disconnect(struct input_handle *handle)
{}

static const struct input_device_id kgdboc_reset_ids[] =;

static struct input_handler kgdboc_reset_handler =;

static DEFINE_MUTEX(kgdboc_reset_mutex);

static void kgdboc_restore_input_helper(struct work_struct *dummy)
{}

static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);

static void kgdboc_queue_restore_input_helper(struct irq_work *unused)
{}

static DEFINE_IRQ_WORK(kgdboc_restore_input_irq_work, kgdboc_queue_restore_input_helper);

static void kgdboc_restore_input(void)
{}

static int kgdboc_register_kbd(char **cptr)
{}

static void kgdboc_unregister_kbd(void)
{}
#else /* ! CONFIG_KDB_KEYBOARD */
#define kgdboc_register_kbd
#define kgdboc_unregister_kbd
#define kgdboc_restore_input
#endif /* ! CONFIG_KDB_KEYBOARD */

#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE)
static void cleanup_earlycon(void)
{}
#else /* !IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */
static inline void cleanup_earlycon(void) { }
#endif /* !IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */

static void cleanup_kgdboc(void)
{}

static int configure_kgdboc(void)
{}

static int kgdboc_probe(struct platform_device *pdev)
{}

static struct platform_driver kgdboc_platform_driver =;

static int __init init_kgdboc(void)
{}

static void exit_kgdboc(void)
{}

static int kgdboc_get_char(void)
{}

static void kgdboc_put_char(u8 chr)
{}

static int param_set_kgdboc_var(const char *kmessage,
				const struct kernel_param *kp)
{}

static int dbg_restore_graphics;

static void kgdboc_pre_exp_handler(void)
{}

static void kgdboc_post_exp_handler(void)
{}

static struct kgdb_io kgdboc_io_ops =;

#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE)
static int kgdboc_option_setup(char *opt)
{}

__setup();


/* This is only available if kgdboc is a built in for early debugging */
static int __init kgdboc_early_init(char *opt)
{}

early_param();

static int kgdboc_earlycon_get_char(void)
{}

static void kgdboc_earlycon_put_char(u8 chr)
{}

static void kgdboc_earlycon_pre_exp_handler(void)
{}

static int kgdboc_earlycon_deferred_exit(struct console *con)
{}

static void kgdboc_earlycon_deinit(void)
{}

static struct kgdb_io kgdboc_earlycon_io_ops =;

#define MAX_CONSOLE_NAME_LEN
static char kgdboc_earlycon_param[MAX_CONSOLE_NAME_LEN] __initdata;
static bool kgdboc_earlycon_late_enable __initdata;

static int __init kgdboc_earlycon_init(char *opt)
{}

early_param();

/*
 * 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!
 */
static int __init kgdboc_earlycon_late_init(void)
{}
console_initcall(kgdboc_earlycon_late_init);

#endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */

module_init();
module_exit(exit_kgdboc);
module_param_call();
MODULE_PARM_DESC();
MODULE_DESCRIPTION();
MODULE_LICENSE();