LCOV - code coverage report
Current view: top level - tty/hvc - hvc_console.c (source / functions) Coverage Total Hit
Test: TTY Combined Coverage Lines: 0.0 % 488 0
Test Date: 2025-08-26 15:45:50 Functions: 0.0 % 32 0

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0+
       2              : /*
       3              :  * Copyright (C) 2001 Anton Blanchard <[email protected]>, IBM
       4              :  * Copyright (C) 2001 Paul Mackerras <[email protected]>, IBM
       5              :  * Copyright (C) 2004 Benjamin Herrenschmidt <[email protected]>, IBM Corp.
       6              :  * Copyright (C) 2004 IBM Corporation
       7              :  *
       8              :  * Additional Author(s):
       9              :  *  Ryan S. Arnold <[email protected]>
      10              :  */
      11              : 
      12              : #include <linux/console.h>
      13              : #include <linux/cpumask.h>
      14              : #include <linux/init.h>
      15              : #include <linux/kbd_kern.h>
      16              : #include <linux/kernel.h>
      17              : #include <linux/kthread.h>
      18              : #include <linux/list.h>
      19              : #include <linux/major.h>
      20              : #include <linux/atomic.h>
      21              : #include <linux/sysrq.h>
      22              : #include <linux/tty.h>
      23              : #include <linux/tty_flip.h>
      24              : #include <linux/sched.h>
      25              : #include <linux/spinlock.h>
      26              : #include <linux/delay.h>
      27              : #include <linux/freezer.h>
      28              : #include <linux/slab.h>
      29              : #include <linux/serial_core.h>
      30              : 
      31              : #include <linux/uaccess.h>
      32              : 
      33              : #include "hvc_console.h"
      34              : 
      35              : #define HVC_MAJOR       229
      36              : #define HVC_MINOR       0
      37              : 
      38              : /*
      39              :  * Wait this long per iteration while trying to push buffered data to the
      40              :  * hypervisor before allowing the tty to complete a close operation.
      41              :  */
      42              : #define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
      43              : 
      44              : /*
      45              :  * These sizes are most efficient for vio, because they are the
      46              :  * native transfer size. We could make them selectable in the
      47              :  * future to better deal with backends that want other buffer sizes.
      48              :  */
      49              : #define N_OUTBUF        16
      50              : #define N_INBUF         16
      51              : 
      52              : #define __ALIGNED__ __attribute__((__aligned__(L1_CACHE_BYTES)))
      53              : 
      54              : static struct tty_driver *hvc_driver;
      55              : static struct task_struct *hvc_task;
      56              : 
      57              : /* Picks up late kicks after list walk but before schedule() */
      58              : static int hvc_kicked;
      59              : 
      60              : /* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
      61              : static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1);
      62              : 
      63              : static int hvc_init(void);
      64              : 
      65              : #ifdef CONFIG_MAGIC_SYSRQ
      66              : static int sysrq_pressed;
      67              : #endif
      68              : 
      69              : /* dynamic list of hvc_struct instances */
      70              : static LIST_HEAD(hvc_structs);
      71              : 
      72              : /*
      73              :  * Protect the list of hvc_struct instances from inserts and removals during
      74              :  * list traversal.
      75              :  */
      76              : static DEFINE_MUTEX(hvc_structs_mutex);
      77              : 
      78              : /*
      79              :  * This value is used to assign a tty->index value to a hvc_struct based
      80              :  * upon order of exposure via hvc_probe(), when we can not match it to
      81              :  * a console candidate registered with hvc_instantiate().
      82              :  */
      83              : static int last_hvc = -1;
      84              : 
      85              : /*
      86              :  * Do not call this function with either the hvc_structs_mutex or the hvc_struct
      87              :  * lock held.  If successful, this function increments the kref reference
      88              :  * count against the target hvc_struct so it should be released when finished.
      89              :  */
      90            0 : static struct hvc_struct *hvc_get_by_index(int index)
      91              : {
      92            0 :         struct hvc_struct *hp;
      93            0 :         unsigned long flags;
      94              : 
      95            0 :         mutex_lock(&hvc_structs_mutex);
      96              : 
      97            0 :         list_for_each_entry(hp, &hvc_structs, next) {
      98            0 :                 spin_lock_irqsave(&hp->lock, flags);
      99            0 :                 if (hp->index == index) {
     100            0 :                         tty_port_get(&hp->port);
     101            0 :                         spin_unlock_irqrestore(&hp->lock, flags);
     102            0 :                         mutex_unlock(&hvc_structs_mutex);
     103            0 :                         return hp;
     104              :                 }
     105            0 :                 spin_unlock_irqrestore(&hp->lock, flags);
     106            0 :         }
     107            0 :         hp = NULL;
     108            0 :         mutex_unlock(&hvc_structs_mutex);
     109              : 
     110            0 :         return hp;
     111            0 : }
     112              : 
     113            0 : static int __hvc_flush(const struct hv_ops *ops, uint32_t vtermno, bool wait)
     114              : {
     115            0 :         if (wait)
     116            0 :                 might_sleep();
     117              : 
     118            0 :         if (ops->flush)
     119            0 :                 return ops->flush(vtermno, wait);
     120            0 :         return 0;
     121            0 : }
     122              : 
     123            0 : static int hvc_console_flush(const struct hv_ops *ops, uint32_t vtermno)
     124              : {
     125            0 :         return __hvc_flush(ops, vtermno, false);
     126              : }
     127              : 
     128              : /*
     129              :  * Wait for the console to flush before writing more to it. This sleeps.
     130              :  */
     131            0 : static int hvc_flush(struct hvc_struct *hp)
     132              : {
     133            0 :         return __hvc_flush(hp->ops, hp->vtermno, true);
     134              : }
     135              : 
     136              : /*
     137              :  * Initial console vtermnos for console API usage prior to full console
     138              :  * initialization.  Any vty adapter outside this range will not have usable
     139              :  * console interfaces but can still be used as a tty device.  This has to be
     140              :  * static because kmalloc will not work during early console init.
     141              :  */
     142              : static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
     143              : static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
     144              :         {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
     145              : 
     146              : /*
     147              :  * Console APIs, NOT TTY.  These APIs are available immediately when
     148              :  * hvc_console_setup() finds adapters.
     149              :  */
     150              : 
     151            0 : static void hvc_console_print(struct console *co, const char *b,
     152              :                               unsigned count)
     153              : {
     154            0 :         char c[N_OUTBUF] __ALIGNED__;
     155            0 :         unsigned i = 0, n = 0;
     156            0 :         int r, donecr = 0, index = co->index;
     157              : 
     158              :         /* Console access attempt outside of acceptable console range. */
     159            0 :         if (index >= MAX_NR_HVC_CONSOLES)
     160            0 :                 return;
     161              : 
     162              :         /* This console adapter was removed so it is not usable. */
     163            0 :         if (vtermnos[index] == -1)
     164            0 :                 return;
     165              : 
     166            0 :         while (count > 0 || i > 0) {
     167            0 :                 if (count > 0 && i < sizeof(c)) {
     168            0 :                         if (b[n] == '\n' && !donecr) {
     169            0 :                                 c[i++] = '\r';
     170            0 :                                 donecr = 1;
     171            0 :                         } else {
     172            0 :                                 c[i++] = b[n++];
     173            0 :                                 donecr = 0;
     174            0 :                                 --count;
     175              :                         }
     176            0 :                 } else {
     177            0 :                         r = cons_ops[index]->put_chars(vtermnos[index], c, i);
     178            0 :                         if (r <= 0) {
     179              :                                 /* throw away characters on error
     180              :                                  * but spin in case of -EAGAIN */
     181            0 :                                 if (r != -EAGAIN) {
     182            0 :                                         i = 0;
     183            0 :                                 } else {
     184            0 :                                         hvc_console_flush(cons_ops[index],
     185            0 :                                                       vtermnos[index]);
     186              :                                 }
     187            0 :                         } else if (r > 0) {
     188            0 :                                 i -= r;
     189            0 :                                 if (i > 0)
     190            0 :                                         memmove(c, c+r, i);
     191            0 :                         }
     192              :                 }
     193              :         }
     194            0 :         hvc_console_flush(cons_ops[index], vtermnos[index]);
     195            0 : }
     196              : 
     197            0 : static struct tty_driver *hvc_console_device(struct console *c, int *index)
     198              : {
     199            0 :         if (vtermnos[c->index] == -1)
     200            0 :                 return NULL;
     201              : 
     202            0 :         *index = c->index;
     203            0 :         return hvc_driver;
     204            0 : }
     205              : 
     206            0 : static int hvc_console_setup(struct console *co, char *options)
     207              : {       
     208            0 :         if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
     209            0 :                 return -ENODEV;
     210              : 
     211            0 :         if (vtermnos[co->index] == -1)
     212            0 :                 return -ENODEV;
     213              : 
     214            0 :         return 0;
     215            0 : }
     216              : 
     217              : static struct console hvc_console = {
     218              :         .name           = "hvc",
     219              :         .write          = hvc_console_print,
     220              :         .device         = hvc_console_device,
     221              :         .setup          = hvc_console_setup,
     222              :         .flags          = CON_PRINTBUFFER,
     223              :         .index          = -1,
     224              : };
     225              : 
     226              : /*
     227              :  * Early console initialization.  Precedes driver initialization.
     228              :  *
     229              :  * (1) we are first, and the user specified another driver
     230              :  * -- index will remain -1
     231              :  * (2) we are first and the user specified no driver
     232              :  * -- index will be set to 0, then we will fail setup.
     233              :  * (3)  we are first and the user specified our driver
     234              :  * -- index will be set to user specified driver, and we will fail
     235              :  * (4) we are after driver, and this initcall will register us
     236              :  * -- if the user didn't specify a driver then the console will match
     237              :  *
     238              :  * Note that for cases 2 and 3, we will match later when the io driver
     239              :  * calls hvc_instantiate() and call register again.
     240              :  */
     241            0 : static int __init hvc_console_init(void)
     242              : {
     243            0 :         register_console(&hvc_console);
     244            0 :         return 0;
     245              : }
     246              : console_initcall(hvc_console_init);
     247              : 
     248              : /* callback when the kboject ref count reaches zero. */
     249            0 : static void hvc_port_destruct(struct tty_port *port)
     250              : {
     251            0 :         struct hvc_struct *hp = container_of(port, struct hvc_struct, port);
     252            0 :         unsigned long flags;
     253              : 
     254            0 :         mutex_lock(&hvc_structs_mutex);
     255              : 
     256            0 :         spin_lock_irqsave(&hp->lock, flags);
     257            0 :         list_del(&(hp->next));
     258            0 :         spin_unlock_irqrestore(&hp->lock, flags);
     259              : 
     260            0 :         mutex_unlock(&hvc_structs_mutex);
     261              : 
     262            0 :         kfree(hp);
     263            0 : }
     264              : 
     265            0 : static void hvc_check_console(int index)
     266              : {
     267              :         /* Already registered, bail out */
     268            0 :         if (console_is_registered(&hvc_console))
     269            0 :                 return;
     270              : 
     271              :         /* If this index is what the user requested, then register
     272              :          * now (setup won't fail at this point).  It's ok to just
     273              :          * call register again if previously .setup failed.
     274              :          */
     275            0 :         if (index == hvc_console.index)
     276            0 :                 register_console(&hvc_console);
     277            0 : }
     278              : 
     279              : /*
     280              :  * hvc_instantiate() is an early console discovery method which locates
     281              :  * consoles * prior to the vio subsystem discovering them.  Hotplugged
     282              :  * vty adapters do NOT get an hvc_instantiate() callback since they
     283              :  * appear after early console init.
     284              :  */
     285            0 : int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
     286              : {
     287            0 :         struct hvc_struct *hp;
     288              : 
     289            0 :         if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
     290            0 :                 return -1;
     291              : 
     292            0 :         if (vtermnos[index] != -1)
     293            0 :                 return -1;
     294              : 
     295              :         /* make sure no tty has been registered in this index */
     296            0 :         hp = hvc_get_by_index(index);
     297            0 :         if (hp) {
     298            0 :                 tty_port_put(&hp->port);
     299            0 :                 return -1;
     300              :         }
     301              : 
     302            0 :         vtermnos[index] = vtermno;
     303            0 :         cons_ops[index] = ops;
     304              : 
     305              :         /* check if we need to re-register the kernel console */
     306            0 :         hvc_check_console(index);
     307              : 
     308            0 :         return 0;
     309            0 : }
     310              : EXPORT_SYMBOL_GPL(hvc_instantiate);
     311              : 
     312              : /* Wake the sleeping khvcd */
     313            0 : void hvc_kick(void)
     314              : {
     315            0 :         hvc_kicked = 1;
     316            0 :         wake_up_process(hvc_task);
     317            0 : }
     318              : EXPORT_SYMBOL_GPL(hvc_kick);
     319              : 
     320            0 : static void hvc_unthrottle(struct tty_struct *tty)
     321              : {
     322            0 :         hvc_kick();
     323            0 : }
     324              : 
     325            0 : static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
     326              : {
     327            0 :         struct hvc_struct *hp;
     328            0 :         int rc;
     329              : 
     330              :         /* Auto increments kref reference if found. */
     331            0 :         hp = hvc_get_by_index(tty->index);
     332            0 :         if (!hp)
     333            0 :                 return -ENODEV;
     334              : 
     335            0 :         tty->driver_data = hp;
     336              : 
     337            0 :         rc = tty_port_install(&hp->port, driver, tty);
     338            0 :         if (rc)
     339            0 :                 tty_port_put(&hp->port);
     340            0 :         return rc;
     341            0 : }
     342              : 
     343              : /*
     344              :  * The TTY interface won't be used until after the vio layer has exposed the vty
     345              :  * adapter to the kernel.
     346              :  */
     347            0 : static int hvc_open(struct tty_struct *tty, struct file * filp)
     348              : {
     349            0 :         struct hvc_struct *hp = tty->driver_data;
     350            0 :         unsigned long flags;
     351            0 :         int rc = 0;
     352              : 
     353            0 :         spin_lock_irqsave(&hp->port.lock, flags);
     354              :         /* Check and then increment for fast path open. */
     355            0 :         if (hp->port.count++ > 0) {
     356            0 :                 spin_unlock_irqrestore(&hp->port.lock, flags);
     357            0 :                 hvc_kick();
     358            0 :                 return 0;
     359              :         } /* else count == 0 */
     360            0 :         spin_unlock_irqrestore(&hp->port.lock, flags);
     361              : 
     362            0 :         tty_port_tty_set(&hp->port, tty);
     363              : 
     364            0 :         if (hp->ops->notifier_add)
     365            0 :                 rc = hp->ops->notifier_add(hp, hp->data);
     366              : 
     367              :         /*
     368              :          * If the notifier fails we return an error.  The tty layer
     369              :          * will call hvc_close() after a failed open but we don't want to clean
     370              :          * up there so we'll clean up here and clear out the previously set
     371              :          * tty fields and return the kref reference.
     372              :          */
     373            0 :         if (rc) {
     374            0 :                 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
     375            0 :         } else {
     376              :                 /* We are ready... raise DTR/RTS */
     377            0 :                 if (C_BAUD(tty))
     378            0 :                         if (hp->ops->dtr_rts)
     379            0 :                                 hp->ops->dtr_rts(hp, true);
     380            0 :                 tty_port_set_initialized(&hp->port, true);
     381              :         }
     382              : 
     383              :         /* Force wakeup of the polling thread */
     384            0 :         hvc_kick();
     385              : 
     386            0 :         return rc;
     387            0 : }
     388              : 
     389            0 : static void hvc_close(struct tty_struct *tty, struct file * filp)
     390              : {
     391            0 :         struct hvc_struct *hp = tty->driver_data;
     392            0 :         unsigned long flags;
     393              : 
     394            0 :         if (tty_hung_up_p(filp))
     395            0 :                 return;
     396              : 
     397            0 :         spin_lock_irqsave(&hp->port.lock, flags);
     398              : 
     399            0 :         if (--hp->port.count == 0) {
     400            0 :                 spin_unlock_irqrestore(&hp->port.lock, flags);
     401              :                 /* We are done with the tty pointer now. */
     402            0 :                 tty_port_tty_set(&hp->port, NULL);
     403              : 
     404            0 :                 if (!tty_port_initialized(&hp->port))
     405            0 :                         return;
     406              : 
     407            0 :                 if (C_HUPCL(tty))
     408            0 :                         if (hp->ops->dtr_rts)
     409            0 :                                 hp->ops->dtr_rts(hp, false);
     410              : 
     411            0 :                 if (hp->ops->notifier_del)
     412            0 :                         hp->ops->notifier_del(hp, hp->data);
     413              : 
     414              :                 /* cancel pending tty resize work */
     415            0 :                 cancel_work_sync(&hp->tty_resize);
     416              : 
     417              :                 /*
     418              :                  * Chain calls chars_in_buffer() and returns immediately if
     419              :                  * there is no buffered data otherwise sleeps on a wait queue
     420              :                  * waking periodically to check chars_in_buffer().
     421              :                  */
     422            0 :                 tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
     423            0 :                 tty_port_set_initialized(&hp->port, false);
     424            0 :         } else {
     425            0 :                 if (hp->port.count < 0)
     426            0 :                         printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
     427              :                                 hp->vtermno, hp->port.count);
     428            0 :                 spin_unlock_irqrestore(&hp->port.lock, flags);
     429              :         }
     430            0 : }
     431              : 
     432            0 : static void hvc_cleanup(struct tty_struct *tty)
     433              : {
     434            0 :         struct hvc_struct *hp = tty->driver_data;
     435              : 
     436            0 :         tty_port_put(&hp->port);
     437            0 : }
     438              : 
     439            0 : static void hvc_hangup(struct tty_struct *tty)
     440              : {
     441            0 :         struct hvc_struct *hp = tty->driver_data;
     442            0 :         unsigned long flags;
     443              : 
     444            0 :         if (!hp)
     445            0 :                 return;
     446              : 
     447              :         /* cancel pending tty resize work */
     448            0 :         cancel_work_sync(&hp->tty_resize);
     449              : 
     450            0 :         spin_lock_irqsave(&hp->port.lock, flags);
     451              : 
     452              :         /*
     453              :          * The N_TTY line discipline has problems such that in a close vs
     454              :          * open->hangup case this can be called after the final close so prevent
     455              :          * that from happening for now.
     456              :          */
     457            0 :         if (hp->port.count <= 0) {
     458            0 :                 spin_unlock_irqrestore(&hp->port.lock, flags);
     459            0 :                 return;
     460              :         }
     461              : 
     462            0 :         hp->port.count = 0;
     463            0 :         spin_unlock_irqrestore(&hp->port.lock, flags);
     464            0 :         tty_port_tty_set(&hp->port, NULL);
     465              : 
     466            0 :         hp->n_outbuf = 0;
     467              : 
     468            0 :         if (hp->ops->notifier_hangup)
     469            0 :                 hp->ops->notifier_hangup(hp, hp->data);
     470            0 : }
     471              : 
     472              : /*
     473              :  * Push buffered characters whether they were just recently buffered or waiting
     474              :  * on a blocked hypervisor.  Call this function with hp->lock held.
     475              :  */
     476            0 : static int hvc_push(struct hvc_struct *hp)
     477              : {
     478            0 :         int n;
     479              : 
     480            0 :         n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
     481            0 :         if (n <= 0) {
     482            0 :                 if (n == 0 || n == -EAGAIN) {
     483            0 :                         hp->do_wakeup = 1;
     484            0 :                         return 0;
     485              :                 }
     486              :                 /* throw away output on error; this happens when
     487              :                    there is no session connected to the vterm. */
     488            0 :                 hp->n_outbuf = 0;
     489            0 :         } else
     490            0 :                 hp->n_outbuf -= n;
     491            0 :         if (hp->n_outbuf > 0)
     492            0 :                 memmove(hp->outbuf, hp->outbuf + n, hp->n_outbuf);
     493              :         else
     494            0 :                 hp->do_wakeup = 1;
     495              : 
     496            0 :         return n;
     497            0 : }
     498              : 
     499            0 : static ssize_t hvc_write(struct tty_struct *tty, const u8 *buf, size_t count)
     500              : {
     501            0 :         struct hvc_struct *hp = tty->driver_data;
     502            0 :         unsigned long flags;
     503            0 :         size_t rsize, written = 0;
     504              : 
     505              :         /* This write was probably executed during a tty close. */
     506            0 :         if (!hp)
     507            0 :                 return -EPIPE;
     508              : 
     509              :         /* FIXME what's this (unprotected) check for? */
     510            0 :         if (hp->port.count <= 0)
     511            0 :                 return -EIO;
     512              : 
     513            0 :         while (count > 0) {
     514            0 :                 int ret = 0;
     515              : 
     516            0 :                 spin_lock_irqsave(&hp->lock, flags);
     517              : 
     518            0 :                 rsize = hp->outbuf_size - hp->n_outbuf;
     519              : 
     520            0 :                 if (rsize) {
     521            0 :                         if (rsize > count)
     522            0 :                                 rsize = count;
     523            0 :                         memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
     524            0 :                         count -= rsize;
     525            0 :                         buf += rsize;
     526            0 :                         hp->n_outbuf += rsize;
     527            0 :                         written += rsize;
     528            0 :                 }
     529              : 
     530            0 :                 if (hp->n_outbuf > 0)
     531            0 :                         ret = hvc_push(hp);
     532              : 
     533            0 :                 spin_unlock_irqrestore(&hp->lock, flags);
     534              : 
     535            0 :                 if (!ret)
     536            0 :                         break;
     537              : 
     538            0 :                 if (count) {
     539            0 :                         if (hp->n_outbuf > 0)
     540            0 :                                 hvc_flush(hp);
     541            0 :                         cond_resched();
     542            0 :                 }
     543            0 :         }
     544              : 
     545              :         /*
     546              :          * Racy, but harmless, kick thread if there is still pending data.
     547              :          */
     548            0 :         if (hp->n_outbuf)
     549            0 :                 hvc_kick();
     550              : 
     551            0 :         return written;
     552            0 : }
     553              : 
     554              : /**
     555              :  * hvc_set_winsz() - Resize the hvc tty terminal window.
     556              :  * @work:       work structure.
     557              :  *
     558              :  * The routine shall not be called within an atomic context because it
     559              :  * might sleep.
     560              :  *
     561              :  * Locking:     hp->lock
     562              :  */
     563            0 : static void hvc_set_winsz(struct work_struct *work)
     564              : {
     565            0 :         struct hvc_struct *hp;
     566            0 :         unsigned long hvc_flags;
     567            0 :         struct tty_struct *tty;
     568            0 :         struct winsize ws;
     569              : 
     570            0 :         hp = container_of(work, struct hvc_struct, tty_resize);
     571              : 
     572            0 :         tty = tty_port_tty_get(&hp->port);
     573            0 :         if (!tty)
     574            0 :                 return;
     575              : 
     576            0 :         spin_lock_irqsave(&hp->lock, hvc_flags);
     577            0 :         ws = hp->ws;
     578            0 :         spin_unlock_irqrestore(&hp->lock, hvc_flags);
     579              : 
     580            0 :         tty_do_resize(tty, &ws);
     581            0 :         tty_kref_put(tty);
     582            0 : }
     583              : 
     584              : /*
     585              :  * This is actually a contract between the driver and the tty layer outlining
     586              :  * how much write room the driver can guarantee will be sent OR BUFFERED.  This
     587              :  * driver MUST honor the return value.
     588              :  */
     589            0 : static unsigned int hvc_write_room(struct tty_struct *tty)
     590              : {
     591            0 :         struct hvc_struct *hp = tty->driver_data;
     592              : 
     593            0 :         if (!hp)
     594            0 :                 return 0;
     595              : 
     596            0 :         return hp->outbuf_size - hp->n_outbuf;
     597            0 : }
     598              : 
     599            0 : static unsigned int hvc_chars_in_buffer(struct tty_struct *tty)
     600              : {
     601            0 :         struct hvc_struct *hp = tty->driver_data;
     602              : 
     603            0 :         if (!hp)
     604            0 :                 return 0;
     605            0 :         return hp->n_outbuf;
     606            0 : }
     607              : 
     608              : /*
     609              :  * timeout will vary between the MIN and MAX values defined here.  By default
     610              :  * and during console activity we will use a default MIN_TIMEOUT of 10.  When
     611              :  * the console is idle, we increase the timeout value on each pass through
     612              :  * msleep until we reach the max.  This may be noticeable as a brief (average
     613              :  * one second) delay on the console before the console responds to input when
     614              :  * there has been no input for some time.
     615              :  */
     616              : #define MIN_TIMEOUT             (10)
     617              : #define MAX_TIMEOUT             (2000)
     618              : static u32 timeout = MIN_TIMEOUT;
     619              : 
     620              : /*
     621              :  * Maximum number of bytes to get from the console driver if hvc_poll is
     622              :  * called from driver (and can't sleep). Any more than this and we break
     623              :  * and start polling with khvcd. This value was derived from an OpenBMC
     624              :  * console with the OPAL driver that results in about 0.25ms interrupts off
     625              :  * latency.
     626              :  */
     627              : #define HVC_ATOMIC_READ_MAX     128
     628              : 
     629              : #define HVC_POLL_READ   0x00000001
     630              : #define HVC_POLL_WRITE  0x00000002
     631              : 
     632            0 : static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
     633              : {
     634            0 :         struct tty_struct *tty;
     635            0 :         int i, n, count, poll_mask = 0;
     636            0 :         char buf[N_INBUF] __ALIGNED__;
     637            0 :         unsigned long flags;
     638            0 :         int read_total = 0;
     639            0 :         int written_total = 0;
     640              : 
     641            0 :         spin_lock_irqsave(&hp->lock, flags);
     642              : 
     643              :         /* Push pending writes */
     644            0 :         if (hp->n_outbuf > 0)
     645            0 :                 written_total = hvc_push(hp);
     646              : 
     647              :         /* Reschedule us if still some write pending */
     648            0 :         if (hp->n_outbuf > 0) {
     649            0 :                 poll_mask |= HVC_POLL_WRITE;
     650              :                 /* If hvc_push() was not able to write, sleep a few msecs */
     651            0 :                 timeout = (written_total) ? 0 : MIN_TIMEOUT;
     652            0 :         }
     653              : 
     654            0 :         if (may_sleep) {
     655            0 :                 spin_unlock_irqrestore(&hp->lock, flags);
     656            0 :                 cond_resched();
     657            0 :                 spin_lock_irqsave(&hp->lock, flags);
     658            0 :         }
     659              : 
     660              :         /* No tty attached, just skip */
     661            0 :         tty = tty_port_tty_get(&hp->port);
     662            0 :         if (tty == NULL)
     663            0 :                 goto bail;
     664              : 
     665              :         /* Now check if we can get data (are we throttled ?) */
     666            0 :         if (tty_throttled(tty))
     667            0 :                 goto out;
     668              : 
     669              :         /* If we aren't notifier driven and aren't throttled, we always
     670              :          * request a reschedule
     671              :          */
     672            0 :         if (!hp->irq_requested)
     673            0 :                 poll_mask |= HVC_POLL_READ;
     674              : 
     675              :  read_again:
     676              :         /* Read data if any */
     677            0 :         count = tty_buffer_request_room(&hp->port, N_INBUF);
     678              : 
     679              :         /* If flip is full, just reschedule a later read */
     680            0 :         if (count == 0) {
     681            0 :                 poll_mask |= HVC_POLL_READ;
     682            0 :                 goto out;
     683              :         }
     684              : 
     685            0 :         n = hp->ops->get_chars(hp->vtermno, buf, count);
     686            0 :         if (n <= 0) {
     687              :                 /* Hangup the tty when disconnected from host */
     688            0 :                 if (n == -EPIPE) {
     689            0 :                         spin_unlock_irqrestore(&hp->lock, flags);
     690            0 :                         tty_hangup(tty);
     691            0 :                         spin_lock_irqsave(&hp->lock, flags);
     692            0 :                 } else if ( n == -EAGAIN ) {
     693              :                         /*
     694              :                          * Some back-ends can only ensure a certain min
     695              :                          * num of bytes read, which may be > 'count'.
     696              :                          * Let the tty clear the flip buff to make room.
     697              :                          */
     698            0 :                         poll_mask |= HVC_POLL_READ;
     699            0 :                 }
     700            0 :                 goto out;
     701              :         }
     702              : 
     703            0 :         for (i = 0; i < n; ++i) {
     704              : #ifdef CONFIG_MAGIC_SYSRQ
     705            0 :                 if (hp->index == hvc_console.index) {
     706              :                         /* Handle the SysRq Hack */
     707              :                         /* XXX should support a sequence */
     708            0 :                         if (buf[i] == '\x0f') { /* ^O */
     709              :                                 /* if ^O is pressed again, reset
     710              :                                  * sysrq_pressed and flip ^O char */
     711            0 :                                 sysrq_pressed = !sysrq_pressed;
     712            0 :                                 if (sysrq_pressed)
     713            0 :                                         continue;
     714            0 :                         } else if (sysrq_pressed) {
     715            0 :                                 handle_sysrq(buf[i]);
     716            0 :                                 sysrq_pressed = 0;
     717            0 :                                 continue;
     718              :                         }
     719            0 :                 }
     720              : #endif /* CONFIG_MAGIC_SYSRQ */
     721            0 :                 tty_insert_flip_char(&hp->port, buf[i], 0);
     722            0 :         }
     723            0 :         read_total += n;
     724              : 
     725            0 :         if (may_sleep) {
     726              :                 /* Keep going until the flip is full */
     727            0 :                 spin_unlock_irqrestore(&hp->lock, flags);
     728            0 :                 cond_resched();
     729            0 :                 spin_lock_irqsave(&hp->lock, flags);
     730            0 :                 goto read_again;
     731            0 :         } else if (read_total < HVC_ATOMIC_READ_MAX) {
     732              :                 /* Break and defer if it's a large read in atomic */
     733            0 :                 goto read_again;
     734              :         }
     735              : 
     736              :         /*
     737              :          * Latency break, schedule another poll immediately.
     738              :          */
     739            0 :         poll_mask |= HVC_POLL_READ;
     740              : 
     741              :  out:
     742              :         /* Wakeup write queue if necessary */
     743            0 :         if (hp->do_wakeup) {
     744            0 :                 hp->do_wakeup = 0;
     745            0 :                 tty_wakeup(tty);
     746            0 :         }
     747              :  bail:
     748            0 :         spin_unlock_irqrestore(&hp->lock, flags);
     749              : 
     750            0 :         if (read_total) {
     751              :                 /* Activity is occurring, so reset the polling backoff value to
     752              :                    a minimum for performance. */
     753            0 :                 timeout = MIN_TIMEOUT;
     754              : 
     755            0 :                 tty_flip_buffer_push(&hp->port);
     756            0 :         }
     757            0 :         tty_kref_put(tty);
     758              : 
     759            0 :         return poll_mask;
     760            0 : }
     761              : 
     762            0 : int hvc_poll(struct hvc_struct *hp)
     763              : {
     764            0 :         return __hvc_poll(hp, false);
     765              : }
     766              : EXPORT_SYMBOL_GPL(hvc_poll);
     767              : 
     768              : /**
     769              :  * __hvc_resize() - Update terminal window size information.
     770              :  * @hp:         HVC console pointer
     771              :  * @ws:         Terminal window size structure
     772              :  *
     773              :  * Stores the specified window size information in the hvc structure of @hp.
     774              :  * The function schedule the tty resize update.
     775              :  *
     776              :  * Locking:     Locking free; the function MUST be called holding hp->lock
     777              :  */
     778            0 : void __hvc_resize(struct hvc_struct *hp, struct winsize ws)
     779              : {
     780            0 :         hp->ws = ws;
     781            0 :         schedule_work(&hp->tty_resize);
     782            0 : }
     783              : EXPORT_SYMBOL_GPL(__hvc_resize);
     784              : 
     785              : /*
     786              :  * This kthread is either polling or interrupt driven.  This is determined by
     787              :  * calling hvc_poll() who determines whether a console adapter support
     788              :  * interrupts.
     789              :  */
     790            0 : static int khvcd(void *unused)
     791              : {
     792            0 :         int poll_mask;
     793            0 :         struct hvc_struct *hp;
     794              : 
     795            0 :         set_freezable();
     796            0 :         do {
     797            0 :                 poll_mask = 0;
     798            0 :                 hvc_kicked = 0;
     799            0 :                 try_to_freeze();
     800            0 :                 wmb();
     801            0 :                 if (!cpus_are_in_xmon()) {
     802            0 :                         mutex_lock(&hvc_structs_mutex);
     803            0 :                         list_for_each_entry(hp, &hvc_structs, next) {
     804            0 :                                 poll_mask |= __hvc_poll(hp, true);
     805            0 :                                 cond_resched();
     806            0 :                         }
     807            0 :                         mutex_unlock(&hvc_structs_mutex);
     808            0 :                 } else
     809            0 :                         poll_mask |= HVC_POLL_READ;
     810            0 :                 if (hvc_kicked)
     811            0 :                         continue;
     812            0 :                 set_current_state(TASK_INTERRUPTIBLE);
     813            0 :                 if (!hvc_kicked) {
     814            0 :                         if (poll_mask == 0)
     815            0 :                                 schedule();
     816              :                         else {
     817            0 :                                 unsigned long j_timeout;
     818              : 
     819            0 :                                 if (timeout < MAX_TIMEOUT)
     820            0 :                                         timeout += (timeout >> 6) + 1;
     821              : 
     822              :                                 /*
     823              :                                  * We don't use msleep_interruptible otherwise
     824              :                                  * "kick" will fail to wake us up
     825              :                                  */
     826            0 :                                 j_timeout = msecs_to_jiffies(timeout) + 1;
     827            0 :                                 schedule_timeout_interruptible(j_timeout);
     828            0 :                         }
     829            0 :                 }
     830            0 :                 __set_current_state(TASK_RUNNING);
     831            0 :         } while (!kthread_should_stop());
     832              : 
     833            0 :         return 0;
     834            0 : }
     835              : 
     836            0 : static int hvc_tiocmget(struct tty_struct *tty)
     837              : {
     838            0 :         struct hvc_struct *hp = tty->driver_data;
     839              : 
     840            0 :         if (!hp || !hp->ops->tiocmget)
     841            0 :                 return -EINVAL;
     842            0 :         return hp->ops->tiocmget(hp);
     843            0 : }
     844              : 
     845            0 : static int hvc_tiocmset(struct tty_struct *tty,
     846              :                         unsigned int set, unsigned int clear)
     847              : {
     848            0 :         struct hvc_struct *hp = tty->driver_data;
     849              : 
     850            0 :         if (!hp || !hp->ops->tiocmset)
     851            0 :                 return -EINVAL;
     852            0 :         return hp->ops->tiocmset(hp, set, clear);
     853            0 : }
     854              : 
     855              : #ifdef CONFIG_CONSOLE_POLL
     856              : static int hvc_poll_init(struct tty_driver *driver, int line, char *options)
     857              : {
     858              :         return 0;
     859              : }
     860              : 
     861              : static int hvc_poll_get_char(struct tty_driver *driver, int line)
     862              : {
     863              :         struct tty_struct *tty = driver->ttys[0];
     864              :         struct hvc_struct *hp = tty->driver_data;
     865              :         int n;
     866              :         char ch;
     867              : 
     868              :         n = hp->ops->get_chars(hp->vtermno, &ch, 1);
     869              : 
     870              :         if (n <= 0)
     871              :                 return NO_POLL_CHAR;
     872              : 
     873              :         return ch;
     874              : }
     875              : 
     876              : static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch)
     877              : {
     878              :         struct tty_struct *tty = driver->ttys[0];
     879              :         struct hvc_struct *hp = tty->driver_data;
     880              :         int n;
     881              : 
     882              :         do {
     883              :                 n = hp->ops->put_chars(hp->vtermno, &ch, 1);
     884              :         } while (n <= 0);
     885              : }
     886              : #endif
     887              : 
     888              : static const struct tty_operations hvc_ops = {
     889              :         .install = hvc_install,
     890              :         .open = hvc_open,
     891              :         .close = hvc_close,
     892              :         .cleanup = hvc_cleanup,
     893              :         .write = hvc_write,
     894              :         .hangup = hvc_hangup,
     895              :         .unthrottle = hvc_unthrottle,
     896              :         .write_room = hvc_write_room,
     897              :         .chars_in_buffer = hvc_chars_in_buffer,
     898              :         .tiocmget = hvc_tiocmget,
     899              :         .tiocmset = hvc_tiocmset,
     900              : #ifdef CONFIG_CONSOLE_POLL
     901              :         .poll_init = hvc_poll_init,
     902              :         .poll_get_char = hvc_poll_get_char,
     903              :         .poll_put_char = hvc_poll_put_char,
     904              : #endif
     905              : };
     906              : 
     907              : static const struct tty_port_operations hvc_port_ops = {
     908              :         .destruct = hvc_port_destruct,
     909              : };
     910              : 
     911            0 : struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
     912              :                              const struct hv_ops *ops,
     913              :                              int outbuf_size)
     914              : {
     915            0 :         struct hvc_struct *hp;
     916            0 :         int i;
     917              : 
     918              :         /* We wait until a driver actually comes along */
     919            0 :         if (atomic_inc_not_zero(&hvc_needs_init)) {
     920            0 :                 int err = hvc_init();
     921            0 :                 if (err)
     922            0 :                         return ERR_PTR(err);
     923            0 :         }
     924              : 
     925            0 :         hp = kzalloc(struct_size(hp, outbuf, outbuf_size), GFP_KERNEL);
     926            0 :         if (!hp)
     927            0 :                 return ERR_PTR(-ENOMEM);
     928              : 
     929            0 :         hp->vtermno = vtermno;
     930            0 :         hp->data = data;
     931            0 :         hp->ops = ops;
     932            0 :         hp->outbuf_size = outbuf_size;
     933              : 
     934            0 :         tty_port_init(&hp->port);
     935            0 :         hp->port.ops = &hvc_port_ops;
     936              : 
     937            0 :         INIT_WORK(&hp->tty_resize, hvc_set_winsz);
     938            0 :         spin_lock_init(&hp->lock);
     939            0 :         mutex_lock(&hvc_structs_mutex);
     940              : 
     941              :         /*
     942              :          * find index to use:
     943              :          * see if this vterm id matches one registered for console.
     944              :          */
     945            0 :         for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
     946            0 :                 if (vtermnos[i] == hp->vtermno &&
     947            0 :                     cons_ops[i] == hp->ops)
     948            0 :                         break;
     949              : 
     950            0 :         if (i >= MAX_NR_HVC_CONSOLES) {
     951              : 
     952              :                 /* find 'empty' slot for console */
     953            0 :                 for (i = 0; i < MAX_NR_HVC_CONSOLES && vtermnos[i] != -1; i++) {
     954            0 :                 }
     955              : 
     956              :                 /* no matching slot, just use a counter */
     957            0 :                 if (i == MAX_NR_HVC_CONSOLES)
     958            0 :                         i = ++last_hvc + MAX_NR_HVC_CONSOLES;
     959            0 :         }
     960              : 
     961            0 :         hp->index = i;
     962            0 :         if (i < MAX_NR_HVC_CONSOLES) {
     963            0 :                 cons_ops[i] = ops;
     964            0 :                 vtermnos[i] = vtermno;
     965            0 :         }
     966              : 
     967            0 :         list_add_tail(&(hp->next), &hvc_structs);
     968            0 :         mutex_unlock(&hvc_structs_mutex);
     969              : 
     970              :         /* check if we need to re-register the kernel console */
     971            0 :         hvc_check_console(i);
     972              : 
     973            0 :         return hp;
     974            0 : }
     975              : EXPORT_SYMBOL_GPL(hvc_alloc);
     976              : 
     977            0 : void hvc_remove(struct hvc_struct *hp)
     978              : {
     979            0 :         unsigned long flags;
     980            0 :         struct tty_struct *tty;
     981              : 
     982            0 :         tty = tty_port_tty_get(&hp->port);
     983              : 
     984            0 :         console_lock();
     985            0 :         spin_lock_irqsave(&hp->lock, flags);
     986            0 :         if (hp->index < MAX_NR_HVC_CONSOLES) {
     987            0 :                 vtermnos[hp->index] = -1;
     988            0 :                 cons_ops[hp->index] = NULL;
     989            0 :         }
     990              : 
     991              :         /* Don't whack hp->irq because tty_hangup() will need to free the irq. */
     992              : 
     993            0 :         spin_unlock_irqrestore(&hp->lock, flags);
     994            0 :         console_unlock();
     995              : 
     996              :         /*
     997              :          * We 'put' the instance that was grabbed when the kref instance
     998              :          * was initialized using kref_init().  Let the last holder of this
     999              :          * kref cause it to be removed, which will probably be the tty_vhangup
    1000              :          * below.
    1001              :          */
    1002            0 :         tty_port_put(&hp->port);
    1003              : 
    1004              :         /*
    1005              :          * This function call will auto chain call hvc_hangup.
    1006              :          */
    1007            0 :         if (tty) {
    1008            0 :                 tty_vhangup(tty);
    1009            0 :                 tty_kref_put(tty);
    1010            0 :         }
    1011            0 : }
    1012              : EXPORT_SYMBOL_GPL(hvc_remove);
    1013              : 
    1014              : /* Driver initialization: called as soon as someone uses hvc_alloc(). */
    1015            0 : static int hvc_init(void)
    1016              : {
    1017            0 :         struct tty_driver *drv;
    1018            0 :         int err;
    1019              : 
    1020              :         /* We need more than hvc_count adapters due to hotplug additions. */
    1021            0 :         drv = tty_alloc_driver(HVC_ALLOC_TTY_ADAPTERS, TTY_DRIVER_REAL_RAW |
    1022              :                         TTY_DRIVER_RESET_TERMIOS);
    1023            0 :         if (IS_ERR(drv)) {
    1024            0 :                 err = PTR_ERR(drv);
    1025            0 :                 goto out;
    1026              :         }
    1027              : 
    1028            0 :         drv->driver_name = "hvc";
    1029            0 :         drv->name = "hvc";
    1030            0 :         drv->major = HVC_MAJOR;
    1031            0 :         drv->minor_start = HVC_MINOR;
    1032            0 :         drv->type = TTY_DRIVER_TYPE_SYSTEM;
    1033            0 :         drv->init_termios = tty_std_termios;
    1034            0 :         tty_set_operations(drv, &hvc_ops);
    1035              : 
    1036              :         /* Always start the kthread because there can be hotplug vty adapters
    1037              :          * added later. */
    1038            0 :         hvc_task = kthread_run(khvcd, NULL, "khvcd");
    1039            0 :         if (IS_ERR(hvc_task)) {
    1040            0 :                 printk(KERN_ERR "Couldn't create kthread for console.\n");
    1041            0 :                 err = PTR_ERR(hvc_task);
    1042            0 :                 goto put_tty;
    1043              :         }
    1044              : 
    1045            0 :         err = tty_register_driver(drv);
    1046            0 :         if (err) {
    1047            0 :                 printk(KERN_ERR "Couldn't register hvc console driver\n");
    1048            0 :                 goto stop_thread;
    1049              :         }
    1050              : 
    1051              :         /*
    1052              :          * Make sure tty is fully registered before allowing it to be
    1053              :          * found by hvc_console_device.
    1054              :          */
    1055            0 :         smp_mb();
    1056            0 :         hvc_driver = drv;
    1057            0 :         return 0;
    1058              : 
    1059              : stop_thread:
    1060            0 :         kthread_stop(hvc_task);
    1061            0 :         hvc_task = NULL;
    1062              : put_tty:
    1063            0 :         tty_driver_kref_put(drv);
    1064              : out:
    1065            0 :         return err;
    1066            0 : }
        

Generated by: LCOV version 2.0-1