|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* This file is licensed under the terms of the GNU General Public
|
|
|
|
* License version 2. This program is licensed "as is" without any
|
|
|
|
* warranty of any kind, whether express or implied.
|
|
|
|
*/
|
|
|
|
#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/module.h>
|
|
|
|
|
|
|
|
#define MAX_CONFIG_LEN 40
|
|
|
|
|
|
|
|
static struct kgdb_io kgdboc_io_ops;
|
|
|
|
|
|
|
|
/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
|
|
|
|
static int configured = -1;
|
|
|
|
|
|
|
|
static char config[MAX_CONFIG_LEN];
|
|
|
|
static struct kparam_string kps = {
|
|
|
|
.string = config,
|
|
|
|
.maxlen = MAX_CONFIG_LEN,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int kgdboc_use_kms; /* 1 if we use kernel mode switching */
|
|
|
|
static struct tty_driver *kgdb_tty_driver;
|
|
|
|
static int kgdb_tty_line;
|
|
|
|
|
|
|
|
#ifdef CONFIG_KDB_KEYBOARD
|
|
|
|
static int kgdboc_reset_connect(struct input_handler *handler,
|
|
|
|
struct input_dev *dev,
|
|
|
|
const struct input_device_id *id)
|
|
|
|
{
|
|
|
|
input_reset_device(dev);
|
|
|
|
|
|
|
|
/* Return an error - we do not want to bind, just to reset */
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kgdboc_reset_disconnect(struct input_handle *handle)
|
|
|
|
{
|
|
|
|
/* We do not expect anyone to actually bind to us */
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct input_device_id kgdboc_reset_ids[] = {
|
|
|
|
{
|
|
|
|
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
|
|
|
|
.evbit = { BIT_MASK(EV_KEY) },
|
|
|
|
},
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct input_handler kgdboc_reset_handler = {
|
|
|
|
.connect = kgdboc_reset_connect,
|
|
|
|
.disconnect = kgdboc_reset_disconnect,
|
|
|
|
.name = "kgdboc_reset",
|
|
|
|
.id_table = kgdboc_reset_ids,
|
|
|
|
};
|
|
|
|
|
|
|
|
static DEFINE_MUTEX(kgdboc_reset_mutex);
|
|
|
|
|
|
|
|
static void 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);
|
|
|
|
|
|
|
|
mutex_unlock(&kgdboc_reset_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
|
|
|
|
|
|
|
|
static void kgdboc_restore_input(void)
|
|
|
|
{
|
|
|
|
if (likely(system_state == SYSTEM_RUNNING))
|
|
|
|
schedule_work(&kgdboc_restore_input_work);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kgdboc_register_kbd(char **cptr)
|
|
|
|
{
|
|
|
|
if (strncmp(*cptr, "kbd", 3) == 0 ||
|
|
|
|
strncmp(*cptr, "kdb", 3) == 0) {
|
|
|
|
if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
|
|
|
|
kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
|
|
|
|
kdb_poll_idx++;
|
|
|
|
if (cptr[0][3] == ',')
|
|
|
|
*cptr += 4;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kgdboc_unregister_kbd(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < kdb_poll_idx; i++) {
|
|
|
|
if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
|
|
|
|
kdb_poll_idx--;
|
|
|
|
kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
|
|
|
|
kdb_poll_funcs[kdb_poll_idx] = NULL;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flush_work(&kgdboc_restore_input_work);
|
|
|
|
}
|
|
|
|
#else /* ! CONFIG_KDB_KEYBOARD */
|
|
|
|
#define kgdboc_register_kbd(x) 0
|
|
|
|
#define kgdboc_unregister_kbd()
|
|
|
|
#define kgdboc_restore_input()
|
|
|
|
#endif /* ! CONFIG_KDB_KEYBOARD */
|
|
|
|
|
|
|
|
static void cleanup_kgdboc(void)
|
|
|
|
{
|
tty/serial: Add kgdb_nmi driver
This special driver makes it possible to temporary use NMI debugger port
as a normal console by issuing 'nmi_console' command (assuming that the
port is attached to KGDB).
Unlike KDB's disable_nmi command, with this driver you are always able
to go back to the debugger using KGDB escape sequence ($3#33). This is
because this console driver processes the input in NMI context, and thus
is able to intercept the magic sequence.
Note that since the console interprets input and uses polling
communication methods, for things like PPP it is still better to fully
detach debugger port from the KGDB NMI (i.e. disable_nmi), and use raw
console.
Usually, to enter the debugger one have to type the magic sequence, so
initially the kernel will print the following prompt on the NMI debugger
console:
Type $3#33 to enter the debugger>
For convenience, there is a kgdb_fiq.knock kernel command line option,
when set to 0, this turns the special command to just a return key
press, so the kernel will be printing this:
Hit <return> to enter the debugger>
This is more convenient for long debugging sessions, although it makes
nmi_console feature somewhat useless.
And for the cases when NMI connected to a dedicated button, the knocking
can be disabled altogether by setting kgdb_fiq.knock to -1.
Suggested-by: Colin Cross <ccross@android.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Alan Cox <alan@linux.intel.com>
Acked-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
12 years ago
|
|
|
if (kgdb_unregister_nmi_console())
|
|
|
|
return;
|
|
|
|
kgdboc_unregister_kbd();
|
|
|
|
if (configured == 1)
|
|
|
|
kgdb_unregister_io_module(&kgdboc_io_ops);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int configure_kgdboc(void)
|
|
|
|
{
|
|
|
|
struct tty_driver *p;
|
|
|
|
int tty_line = 0;
|
|
|
|
int err = -ENODEV;
|
|
|
|
char *cptr = config;
|
|
|
|
struct console *cons;
|
|
|
|
|
|
|
|
if (!strlen(config) || isspace(config[0])) {
|
|
|
|
err = 0;
|
|
|
|
goto noconfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
kgdboc_io_ops.is_console = 0;
|
|
|
|
kgdb_tty_driver = NULL;
|
|
|
|
|
|
|
|
kgdboc_use_kms = 0;
|
|
|
|
if (strncmp(cptr, "kms,", 4) == 0) {
|
|
|
|
cptr += 4;
|
|
|
|
kgdboc_use_kms = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kgdboc_register_kbd(&cptr))
|
|
|
|
goto do_register;
|
|
|
|
|
|
|
|
p = tty_find_polling_driver(cptr, &tty_line);
|
|
|
|
if (!p)
|
|
|
|
goto noconfig;
|
|
|
|
|
|
|
|
cons = console_drivers;
|
|
|
|
while (cons) {
|
|
|
|
int idx;
|
|
|
|
if (cons->device && cons->device(cons, &idx) == p &&
|
|
|
|
idx == tty_line) {
|
|
|
|
kgdboc_io_ops.is_console = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cons = cons->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
kgdb_tty_driver = p;
|
|
|
|
kgdb_tty_line = tty_line;
|
|
|
|
|
|
|
|
do_register:
|
|
|
|
err = kgdb_register_io_module(&kgdboc_io_ops);
|
|
|
|
if (err)
|
|
|
|
goto noconfig;
|
|
|
|
|
tty/serial: Add kgdb_nmi driver
This special driver makes it possible to temporary use NMI debugger port
as a normal console by issuing 'nmi_console' command (assuming that the
port is attached to KGDB).
Unlike KDB's disable_nmi command, with this driver you are always able
to go back to the debugger using KGDB escape sequence ($3#33). This is
because this console driver processes the input in NMI context, and thus
is able to intercept the magic sequence.
Note that since the console interprets input and uses polling
communication methods, for things like PPP it is still better to fully
detach debugger port from the KGDB NMI (i.e. disable_nmi), and use raw
console.
Usually, to enter the debugger one have to type the magic sequence, so
initially the kernel will print the following prompt on the NMI debugger
console:
Type $3#33 to enter the debugger>
For convenience, there is a kgdb_fiq.knock kernel command line option,
when set to 0, this turns the special command to just a return key
press, so the kernel will be printing this:
Hit <return> to enter the debugger>
This is more convenient for long debugging sessions, although it makes
nmi_console feature somewhat useless.
And for the cases when NMI connected to a dedicated button, the knocking
can be disabled altogether by setting kgdb_fiq.knock to -1.
Suggested-by: Colin Cross <ccross@android.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Alan Cox <alan@linux.intel.com>
Acked-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
12 years ago
|
|
|
err = kgdb_register_nmi_console();
|
|
|
|
if (err)
|
|
|
|
goto nmi_con_failed;
|
|
|
|
|
|
|
|
configured = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
tty/serial: Add kgdb_nmi driver
This special driver makes it possible to temporary use NMI debugger port
as a normal console by issuing 'nmi_console' command (assuming that the
port is attached to KGDB).
Unlike KDB's disable_nmi command, with this driver you are always able
to go back to the debugger using KGDB escape sequence ($3#33). This is
because this console driver processes the input in NMI context, and thus
is able to intercept the magic sequence.
Note that since the console interprets input and uses polling
communication methods, for things like PPP it is still better to fully
detach debugger port from the KGDB NMI (i.e. disable_nmi), and use raw
console.
Usually, to enter the debugger one have to type the magic sequence, so
initially the kernel will print the following prompt on the NMI debugger
console:
Type $3#33 to enter the debugger>
For convenience, there is a kgdb_fiq.knock kernel command line option,
when set to 0, this turns the special command to just a return key
press, so the kernel will be printing this:
Hit <return> to enter the debugger>
This is more convenient for long debugging sessions, although it makes
nmi_console feature somewhat useless.
And for the cases when NMI connected to a dedicated button, the knocking
can be disabled altogether by setting kgdb_fiq.knock to -1.
Suggested-by: Colin Cross <ccross@android.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Alan Cox <alan@linux.intel.com>
Acked-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
12 years ago
|
|
|
nmi_con_failed:
|
|
|
|
kgdb_unregister_io_module(&kgdboc_io_ops);
|
|
|
|
noconfig:
|
tty/serial: Add kgdb_nmi driver
This special driver makes it possible to temporary use NMI debugger port
as a normal console by issuing 'nmi_console' command (assuming that the
port is attached to KGDB).
Unlike KDB's disable_nmi command, with this driver you are always able
to go back to the debugger using KGDB escape sequence ($3#33). This is
because this console driver processes the input in NMI context, and thus
is able to intercept the magic sequence.
Note that since the console interprets input and uses polling
communication methods, for things like PPP it is still better to fully
detach debugger port from the KGDB NMI (i.e. disable_nmi), and use raw
console.
Usually, to enter the debugger one have to type the magic sequence, so
initially the kernel will print the following prompt on the NMI debugger
console:
Type $3#33 to enter the debugger>
For convenience, there is a kgdb_fiq.knock kernel command line option,
when set to 0, this turns the special command to just a return key
press, so the kernel will be printing this:
Hit <return> to enter the debugger>
This is more convenient for long debugging sessions, although it makes
nmi_console feature somewhat useless.
And for the cases when NMI connected to a dedicated button, the knocking
can be disabled altogether by setting kgdb_fiq.knock to -1.
Suggested-by: Colin Cross <ccross@android.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Alan Cox <alan@linux.intel.com>
Acked-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
12 years ago
|
|
|
kgdboc_unregister_kbd();
|
|
|
|
config[0] = 0;
|
|
|
|
configured = 0;
|
|
|
|
cleanup_kgdboc();
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init init_kgdboc(void)
|
|
|
|
{
|
|
|
|
/* Already configured? */
|
|
|
|
if (configured == 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return configure_kgdboc();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kgdboc_get_char(void)
|
|
|
|
{
|
|
|
|
if (!kgdb_tty_driver)
|
|
|
|
return -1;
|
|
|
|
return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
|
|
|
|
kgdb_tty_line);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kgdboc_put_char(u8 chr)
|
|
|
|
{
|
|
|
|
if (!kgdb_tty_driver)
|
|
|
|
return;
|
|
|
|
kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
|
|
|
|
kgdb_tty_line, chr);
|
|
|
|
}
|
|
|
|
|
UPSTREAM: treewide: Fix function prototypes for module_param_call()
Several function prototypes for the set/get functions defined by
module_param_call() have a slightly wrong argument types. This fixes
those in an effort to clean up the calls when running under type-enforced
compiler instrumentation for CFI. This is the result of running the
following semantic patch:
@match_module_param_call_function@
declarer name module_param_call;
identifier _name, _set_func, _get_func;
expression _arg, _mode;
@@
module_param_call(_name, _set_func, _get_func, _arg, _mode);
@fix_set_prototype
depends on match_module_param_call_function@
identifier match_module_param_call_function._set_func;
identifier _val, _param;
type _val_type, _param_type;
@@
int _set_func(
-_val_type _val
+const char * _val
,
-_param_type _param
+const struct kernel_param * _param
) { ... }
@fix_get_prototype
depends on match_module_param_call_function@
identifier match_module_param_call_function._get_func;
identifier _val, _param;
type _val_type, _param_type;
@@
int _get_func(
-_val_type _val
+char * _val
,
-_param_type _param
+const struct kernel_param * _param
) { ... }
Two additional by-hand changes are included for places where the above
Coccinelle script didn't notice them:
drivers/platform/x86/thinkpad_acpi.c
fs/lockd/svc.c
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Jessica Yu <jeyu@kernel.org>
Bug: 67506682
Change-Id: I2c9c0ee8ed28065e63270a52c155e5e7d2791295
(cherry picked from commit e4dca7b7aa08b22893c45485d222b5807c1375ae)
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
7 years ago
|
|
|
static int param_set_kgdboc_var(const char *kmessage,
|
|
|
|
const struct kernel_param *kp)
|
|
|
|
{
|
|
|
|
size_t len = strlen(kmessage);
|
|
|
|
|
|
|
|
if (len >= MAX_CONFIG_LEN) {
|
|
|
|
printk(KERN_ERR "kgdboc: config string too long\n");
|
|
|
|
return -ENOSPC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only copy in the string if the init function has not run yet */
|
|
|
|
if (configured < 0) {
|
|
|
|
strcpy(config, kmessage);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kgdb_connected) {
|
|
|
|
printk(KERN_ERR
|
|
|
|
"kgdboc: Cannot reconfigure while KGDB is connected.\n");
|
|
|
|
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
/* Go and configure with the new params. */
|
|
|
|
return configure_kgdboc();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dbg_restore_graphics;
|
|
|
|
|
|
|
|
static void 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void 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();
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct kgdb_io kgdboc_io_ops = {
|
|
|
|
.name = "kgdboc",
|
|
|
|
.read_char = kgdboc_get_char,
|
|
|
|
.write_char = kgdboc_put_char,
|
|
|
|
.pre_exception = kgdboc_pre_exp_handler,
|
|
|
|
.post_exception = kgdboc_post_exp_handler,
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef CONFIG_KGDB_SERIAL_CONSOLE
|
|
|
|
static int kgdboc_option_setup(char *opt)
|
|
|
|
{
|
|
|
|
if (!opt) {
|
|
|
|
pr_err("config string not provided\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen(opt) >= MAX_CONFIG_LEN) {
|
|
|
|
pr_err("config string too long\n");
|
|
|
|
return -ENOSPC;
|
|
|
|
}
|
|
|
|
strcpy(config, opt);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
__setup("kgdboc=", kgdboc_option_setup);
|
|
|
|
|
|
|
|
|
|
|
|
/* This is only available if kgdboc is a built in for early debugging */
|
|
|
|
static int __init kgdboc_early_init(char *opt)
|
|
|
|
{
|
|
|
|
/* save the first character of the config string because the
|
|
|
|
* init routine can destroy it.
|
|
|
|
*/
|
|
|
|
char save_ch;
|
|
|
|
|
|
|
|
kgdboc_option_setup(opt);
|
|
|
|
save_ch = config[0];
|
|
|
|
init_kgdboc();
|
|
|
|
config[0] = save_ch;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
early_param("ekgdboc", kgdboc_early_init);
|
|
|
|
#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
|
|
|
|
|
|
|
|
module_init(init_kgdboc);
|
|
|
|
module_exit(cleanup_kgdboc);
|
|
|
|
module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
|
|
|
|
MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
|
|
|
|
MODULE_DESCRIPTION("KGDB Console TTY Driver");
|
|
|
|
MODULE_LICENSE("GPL");
|