root/drivers/tty/serial/kgdboc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kgdboc_reset_connect
  2. kgdboc_reset_disconnect
  3. kgdboc_restore_input_helper
  4. kgdboc_restore_input
  5. kgdboc_register_kbd
  6. kgdboc_unregister_kbd
  7. cleanup_kgdboc
  8. configure_kgdboc
  9. init_kgdboc
  10. kgdboc_get_char
  11. kgdboc_put_char
  12. param_set_kgdboc_var
  13. kgdboc_pre_exp_handler
  14. kgdboc_post_exp_handler
  15. kgdboc_option_setup
  16. kgdboc_early_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Based on the same principle as kgdboe using the NETPOLL api, this
   4  * driver uses a console polling api to implement a gdb serial inteface
   5  * which is multiplexed on a console port.
   6  *
   7  * Maintainer: Jason Wessel <jason.wessel@windriver.com>
   8  *
   9  * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
  10  */
  11 
  12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/ctype.h>
  16 #include <linux/kgdb.h>
  17 #include <linux/kdb.h>
  18 #include <linux/tty.h>
  19 #include <linux/console.h>
  20 #include <linux/vt_kern.h>
  21 #include <linux/input.h>
  22 #include <linux/module.h>
  23 
  24 #define MAX_CONFIG_LEN          40
  25 
  26 static struct kgdb_io           kgdboc_io_ops;
  27 
  28 /* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
  29 static int configured           = -1;
  30 
  31 static char config[MAX_CONFIG_LEN];
  32 static struct kparam_string kps = {
  33         .string                 = config,
  34         .maxlen                 = MAX_CONFIG_LEN,
  35 };
  36 
  37 static int kgdboc_use_kms;  /* 1 if we use kernel mode switching */
  38 static struct tty_driver        *kgdb_tty_driver;
  39 static int                      kgdb_tty_line;
  40 
  41 #ifdef CONFIG_KDB_KEYBOARD
  42 static int kgdboc_reset_connect(struct input_handler *handler,
  43                                 struct input_dev *dev,
  44                                 const struct input_device_id *id)
  45 {
  46         input_reset_device(dev);
  47 
  48         /* Return an error - we do not want to bind, just to reset */
  49         return -ENODEV;
  50 }
  51 
  52 static void kgdboc_reset_disconnect(struct input_handle *handle)
  53 {
  54         /* We do not expect anyone to actually bind to us */
  55         BUG();
  56 }
  57 
  58 static const struct input_device_id kgdboc_reset_ids[] = {
  59         {
  60                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
  61                 .evbit = { BIT_MASK(EV_KEY) },
  62         },
  63         { }
  64 };
  65 
  66 static struct input_handler kgdboc_reset_handler = {
  67         .connect        = kgdboc_reset_connect,
  68         .disconnect     = kgdboc_reset_disconnect,
  69         .name           = "kgdboc_reset",
  70         .id_table       = kgdboc_reset_ids,
  71 };
  72 
  73 static DEFINE_MUTEX(kgdboc_reset_mutex);
  74 
  75 static void kgdboc_restore_input_helper(struct work_struct *dummy)
  76 {
  77         /*
  78          * We need to take a mutex to prevent several instances of
  79          * this work running on different CPUs so they don't try
  80          * to register again already registered handler.
  81          */
  82         mutex_lock(&kgdboc_reset_mutex);
  83 
  84         if (input_register_handler(&kgdboc_reset_handler) == 0)
  85                 input_unregister_handler(&kgdboc_reset_handler);
  86 
  87         mutex_unlock(&kgdboc_reset_mutex);
  88 }
  89 
  90 static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
  91 
  92 static void kgdboc_restore_input(void)
  93 {
  94         if (likely(system_state == SYSTEM_RUNNING))
  95                 schedule_work(&kgdboc_restore_input_work);
  96 }
  97 
  98 static int kgdboc_register_kbd(char **cptr)
  99 {
 100         if (strncmp(*cptr, "kbd", 3) == 0 ||
 101                 strncmp(*cptr, "kdb", 3) == 0) {
 102                 if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
 103                         kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
 104                         kdb_poll_idx++;
 105                         if (cptr[0][3] == ',')
 106                                 *cptr += 4;
 107                         else
 108                                 return 1;
 109                 }
 110         }
 111         return 0;
 112 }
 113 
 114 static void kgdboc_unregister_kbd(void)
 115 {
 116         int i;
 117 
 118         for (i = 0; i < kdb_poll_idx; i++) {
 119                 if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
 120                         kdb_poll_idx--;
 121                         kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
 122                         kdb_poll_funcs[kdb_poll_idx] = NULL;
 123                         i--;
 124                 }
 125         }
 126         flush_work(&kgdboc_restore_input_work);
 127 }
 128 #else /* ! CONFIG_KDB_KEYBOARD */
 129 #define kgdboc_register_kbd(x) 0
 130 #define kgdboc_unregister_kbd()
 131 #define kgdboc_restore_input()
 132 #endif /* ! CONFIG_KDB_KEYBOARD */
 133 
 134 static void cleanup_kgdboc(void)
 135 {
 136         if (kgdb_unregister_nmi_console())
 137                 return;
 138         kgdboc_unregister_kbd();
 139         if (configured == 1)
 140                 kgdb_unregister_io_module(&kgdboc_io_ops);
 141 }
 142 
 143 static int configure_kgdboc(void)
 144 {
 145         struct tty_driver *p;
 146         int tty_line = 0;
 147         int err = -ENODEV;
 148         char *cptr = config;
 149         struct console *cons;
 150 
 151         if (!strlen(config) || isspace(config[0])) {
 152                 err = 0;
 153                 goto noconfig;
 154         }
 155 
 156         kgdboc_io_ops.is_console = 0;
 157         kgdb_tty_driver = NULL;
 158 
 159         kgdboc_use_kms = 0;
 160         if (strncmp(cptr, "kms,", 4) == 0) {
 161                 cptr += 4;
 162                 kgdboc_use_kms = 1;
 163         }
 164 
 165         if (kgdboc_register_kbd(&cptr))
 166                 goto do_register;
 167 
 168         p = tty_find_polling_driver(cptr, &tty_line);
 169         if (!p)
 170                 goto noconfig;
 171 
 172         cons = console_drivers;
 173         while (cons) {
 174                 int idx;
 175                 if (cons->device && cons->device(cons, &idx) == p &&
 176                     idx == tty_line) {
 177                         kgdboc_io_ops.is_console = 1;
 178                         break;
 179                 }
 180                 cons = cons->next;
 181         }
 182 
 183         kgdb_tty_driver = p;
 184         kgdb_tty_line = tty_line;
 185 
 186 do_register:
 187         err = kgdb_register_io_module(&kgdboc_io_ops);
 188         if (err)
 189                 goto noconfig;
 190 
 191         err = kgdb_register_nmi_console();
 192         if (err)
 193                 goto nmi_con_failed;
 194 
 195         configured = 1;
 196 
 197         return 0;
 198 
 199 nmi_con_failed:
 200         kgdb_unregister_io_module(&kgdboc_io_ops);
 201 noconfig:
 202         kgdboc_unregister_kbd();
 203         config[0] = 0;
 204         configured = 0;
 205         cleanup_kgdboc();
 206 
 207         return err;
 208 }
 209 
 210 static int __init init_kgdboc(void)
 211 {
 212         /* Already configured? */
 213         if (configured == 1)
 214                 return 0;
 215 
 216         return configure_kgdboc();
 217 }
 218 
 219 static int kgdboc_get_char(void)
 220 {
 221         if (!kgdb_tty_driver)
 222                 return -1;
 223         return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
 224                                                 kgdb_tty_line);
 225 }
 226 
 227 static void kgdboc_put_char(u8 chr)
 228 {
 229         if (!kgdb_tty_driver)
 230                 return;
 231         kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
 232                                         kgdb_tty_line, chr);
 233 }
 234 
 235 static int param_set_kgdboc_var(const char *kmessage,
 236                                 const struct kernel_param *kp)
 237 {
 238         size_t len = strlen(kmessage);
 239 
 240         if (len >= MAX_CONFIG_LEN) {
 241                 pr_err("config string too long\n");
 242                 return -ENOSPC;
 243         }
 244 
 245         /* Only copy in the string if the init function has not run yet */
 246         if (configured < 0) {
 247                 strcpy(config, kmessage);
 248                 return 0;
 249         }
 250 
 251         if (kgdb_connected) {
 252                 pr_err("Cannot reconfigure while KGDB is connected.\n");
 253 
 254                 return -EBUSY;
 255         }
 256 
 257         strcpy(config, kmessage);
 258         /* Chop out \n char as a result of echo */
 259         if (len && config[len - 1] == '\n')
 260                 config[len - 1] = '\0';
 261 
 262         if (configured == 1)
 263                 cleanup_kgdboc();
 264 
 265         /* Go and configure with the new params. */
 266         return configure_kgdboc();
 267 }
 268 
 269 static int dbg_restore_graphics;
 270 
 271 static void kgdboc_pre_exp_handler(void)
 272 {
 273         if (!dbg_restore_graphics && kgdboc_use_kms) {
 274                 dbg_restore_graphics = 1;
 275                 con_debug_enter(vc_cons[fg_console].d);
 276         }
 277         /* Increment the module count when the debugger is active */
 278         if (!kgdb_connected)
 279                 try_module_get(THIS_MODULE);
 280 
 281         atomic_inc(&ignore_console_lock_warning);
 282 }
 283 
 284 static void kgdboc_post_exp_handler(void)
 285 {
 286         atomic_dec(&ignore_console_lock_warning);
 287 
 288         /* decrement the module count when the debugger detaches */
 289         if (!kgdb_connected)
 290                 module_put(THIS_MODULE);
 291         if (kgdboc_use_kms && dbg_restore_graphics) {
 292                 dbg_restore_graphics = 0;
 293                 con_debug_leave();
 294         }
 295         kgdboc_restore_input();
 296 }
 297 
 298 static struct kgdb_io kgdboc_io_ops = {
 299         .name                   = "kgdboc",
 300         .read_char              = kgdboc_get_char,
 301         .write_char             = kgdboc_put_char,
 302         .pre_exception          = kgdboc_pre_exp_handler,
 303         .post_exception         = kgdboc_post_exp_handler,
 304 };
 305 
 306 #ifdef CONFIG_KGDB_SERIAL_CONSOLE
 307 static int kgdboc_option_setup(char *opt)
 308 {
 309         if (!opt) {
 310                 pr_err("config string not provided\n");
 311                 return -EINVAL;
 312         }
 313 
 314         if (strlen(opt) >= MAX_CONFIG_LEN) {
 315                 pr_err("config string too long\n");
 316                 return -ENOSPC;
 317         }
 318         strcpy(config, opt);
 319 
 320         return 0;
 321 }
 322 
 323 __setup("kgdboc=", kgdboc_option_setup);
 324 
 325 
 326 /* This is only available if kgdboc is a built in for early debugging */
 327 static int __init kgdboc_early_init(char *opt)
 328 {
 329         /* save the first character of the config string because the
 330          * init routine can destroy it.
 331          */
 332         char save_ch;
 333 
 334         kgdboc_option_setup(opt);
 335         save_ch = config[0];
 336         init_kgdboc();
 337         config[0] = save_ch;
 338         return 0;
 339 }
 340 
 341 early_param("ekgdboc", kgdboc_early_init);
 342 #endif /* CONFIG_KGDB_SERIAL_CONSOLE */
 343 
 344 module_init(init_kgdboc);
 345 module_exit(cleanup_kgdboc);
 346 module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
 347 MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
 348 MODULE_DESCRIPTION("KGDB Console TTY Driver");
 349 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */