1 /*
2 * Copyright (c) 2015 Julien Grall <julien.grall@citrix.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/module.h>
32 #include <sys/systm.h>
33 #include <sys/eventhandler.h>
34 #include <sys/consio.h>
35 #include <sys/priv.h>
36 #include <sys/proc.h>
37 #include <sys/uio.h>
38 #include <sys/tty.h>
39 #include <sys/systm.h>
40 #include <sys/taskqueue.h>
41 #include <sys/conf.h>
42 #include <sys/kernel.h>
43 #include <sys/bus.h>
44 #include <sys/cons.h>
45 #include <sys/kdb.h>
46 #include <sys/proc.h>
47 #include <sys/reboot.h>
48
49 #include <machine/stdarg.h>
50
51 #include <vm/vm.h>
52 #include <vm/pmap.h>
53
54 #include <xen/xen-os.h>
55 #include <xen/hypervisor.h>
56 #include <xen/xen_intr.h>
57 #include <contrib/xen/io/console.h>
58
59 #include "opt_ddb.h"
60 #include "opt_printf.h"
61
62 #ifdef DDB
63 #include <ddb/ddb.h>
64 #endif
65
66 static char driver_name[] = "xc";
67
68 struct xencons_priv;
69
70 typedef void xencons_early_init_t(struct xencons_priv *cons);
71 typedef int xencons_init_t(device_t dev, struct tty *tp,
72 driver_intr_t intr_handler);
73 typedef int xencons_read_t(struct xencons_priv *cons, char *buffer,
74 unsigned int size);
75 typedef int xencons_write_t(struct xencons_priv *cons, const char *buffer,
76 unsigned int size);
77
78 struct xencons_ops {
79 /*
80 * Called by the low-level driver during early boot.
81 * Only the minimal set up to get a console should be done here.
82 */
83 xencons_early_init_t *early_init;
84 /* Prepare the console to be fully use */
85 xencons_init_t *init;
86 /* Read/write helpers */
87 xencons_read_t *read;
88 xencons_write_t *write;
89 };
90
91 struct xencons_priv {
92 /* Mutex to protect the shared ring and the internal buffers */
93 struct mtx mtx;
94 /* Interrupt handler used for notify the backend */
95 xen_intr_handle_t intr_handle;
96 /* KDB internal state */
97 #ifdef KDB
98 int altbrk;
99 #endif
100 /* Status of the tty */
101 bool opened;
102 /* Callout used when the write buffer is full */
103 struct callout callout;
104
105 /* Internal buffers must be used with mtx locked */
106 #define WBUF_SIZE 4096
107 #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
108 char wbuf[WBUF_SIZE];
109 unsigned int wc, wp; /* Consumer/producer wbuf */
110
111 #define RBUF_SIZE 1024
112 #define RBUF_MASK(_i) ((_i)&(RBUF_SIZE-1))
113 char rbuf[RBUF_SIZE];
114 unsigned int rc, rp; /* Consumer/producer rbuf */
115
116 /* Pointer to the console operations */
117 const struct xencons_ops *ops;
118
119 /*
120 * Ring specific fields
121 * XXX: make an union?
122 */
123 /* Event channel number for early notification (PV only) */
124 uint32_t evtchn;
125 /* Console shared page */
126 struct xencons_interface *intf;
127 };
128
129 /*
130 * Data for the main console
131 * Necessary to support low-level console driver
132 */
133 static struct xencons_priv main_cons;
134
135 #define XC_POLLTIME (hz/10)
136
137 /*----------------------------- Debug function ------------------------------*/
138 struct putchar_arg {
139 char *buf;
140 size_t size;
141 size_t n_next;
142 };
143
144 static void
145 putchar(int c, void *arg)
146 {
147 struct putchar_arg *pca;
148
149 pca = (struct putchar_arg *)arg;
150
151 if (pca->buf == NULL) {
152 /*
153 * We have no buffer, output directly to the
154 * console char by char.
155 */
156 HYPERVISOR_console_write((char *)&c, 1);
157 } else {
158 pca->buf[pca->n_next++] = c;
159 if ((pca->size == pca->n_next) || (c = '\0')) {
160 /* Flush the buffer */
161 HYPERVISOR_console_write(pca->buf, pca->n_next);
162 pca->n_next = 0;
163 }
164 }
165 }
166
167 void
168 xc_printf(const char *fmt, ...)
169 {
170 va_list ap;
171 struct putchar_arg pca;
172 #ifdef PRINTF_BUFR_SIZE
173 char buf[PRINTF_BUFR_SIZE];
174
175 pca.buf = buf;
176 pca.size = sizeof(buf);
177 pca.n_next = 0;
178 #else
179 pca.buf = NULL;
180 pca.size = 0;
181 #endif
182
183 KASSERT((xen_domain()), ("call to xc_printf from non Xen guest"));
184
185 va_start(ap, fmt);
186 kvprintf(fmt, putchar, &pca, 10, ap);
187 va_end(ap);
188
189 #ifdef PRINTF_BUFR_SIZE
190 if (pca.n_next != 0)
191 HYPERVISOR_console_write(buf, pca.n_next);
192 #endif
193 }
194
195 /*---------------------- Helpers for the console lock -----------------------*/
196 /*
197 * The lock is not used when the kernel is panicing as it will never recover
198 * and we want to output no matter what it costs.
199 */
200 static inline void xencons_lock(struct xencons_priv *cons)
201 {
202
203 if (!KERNEL_PANICKED())
204 mtx_lock_spin(&cons->mtx);
205
206 }
207
208 static inline void xencons_unlock(struct xencons_priv *cons)
209 {
210
211 if (!KERNEL_PANICKED())
212 mtx_unlock_spin(&cons->mtx);
213 }
214
215 #define xencons_lock_assert(cons) mtx_assert(&(cons)->mtx, MA_OWNED)
216
217 /*------------------ Helpers for the hypervisor console ---------------------*/
218 static void
219 xencons_early_init_hypervisor(struct xencons_priv *cons)
220 {
221 /*
222 * Nothing to setup for the low-level console when using
223 * the hypervisor console.
224 */
225 }
226
227 static int
228 xencons_init_hypervisor(device_t dev, struct tty *tp,
229 driver_intr_t intr_handler)
230 {
231 struct xencons_priv *cons;
232 int err;
233
234 cons = tty_softc(tp);
235
236 err = xen_intr_bind_virq(dev, VIRQ_CONSOLE, 0, NULL,
237 intr_handler, tp, INTR_TYPE_TTY | INTR_MPSAFE, &cons->intr_handle);
238 if (err != 0)
239 device_printf(dev, "Can't register console interrupt\n");
240
241 return (err);
242 }
243
244 static int
245 xencons_write_hypervisor(struct xencons_priv *cons, const char *buffer,
246 unsigned int size)
247 {
248
249 HYPERVISOR_console_io(CONSOLEIO_write, size, buffer);
250
251 return (size);
252 }
253
254 static int
255 xencons_read_hypervisor(struct xencons_priv *cons, char *buffer,
256 unsigned int size)
257 {
258
259 xencons_lock_assert(cons);
260
261 return (HYPERVISOR_console_io(CONSOLEIO_read, size, buffer));
262 }
263
264 static const struct xencons_ops xencons_hypervisor_ops = {
265 .early_init = xencons_early_init_hypervisor,
266 .init = xencons_init_hypervisor,
267 .read = xencons_read_hypervisor,
268 .write = xencons_write_hypervisor,
269 };
270
271 /*------------------ Helpers for the ring console ---------------------------*/
272 static void
273 xencons_early_init_ring(struct xencons_priv *cons)
274 {
275 cons->intf = pmap_mapdev_attr(ptoa(xen_get_console_mfn()), PAGE_SIZE,
276 VM_MEMATTR_XEN);
277 cons->evtchn = xen_get_console_evtchn();
278 }
279
280 static int
281 xencons_init_ring(device_t dev, struct tty *tp, driver_intr_t intr_handler)
282 {
283 struct xencons_priv *cons;
284 int err;
285
286 cons = tty_softc(tp);
287
288 if (cons->evtchn == 0)
289 return (ENODEV);
290
291 err = xen_intr_bind_local_port(dev, cons->evtchn, NULL,
292 intr_handler, tp, INTR_TYPE_TTY | INTR_MPSAFE, &cons->intr_handle);
293 if (err != 0)
294 return (err);
295
296 return (0);
297 }
298
299 static void
300 xencons_notify_ring(struct xencons_priv *cons)
301 {
302 /*
303 * The console may be used before the ring interrupt is properly
304 * initialized.
305 * If so, fallback to directly use the event channel hypercall.
306 */
307 if (__predict_true(cons->intr_handle != NULL))
308 xen_intr_signal(cons->intr_handle);
309 else {
310 struct evtchn_send send = {
311 .port = cons->evtchn
312 };
313
314 HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);
315 }
316 }
317
318 static int
319 xencons_write_ring(struct xencons_priv *cons, const char *buffer,
320 unsigned int size)
321 {
322 struct xencons_interface *intf;
323 XENCONS_RING_IDX wcons, wprod;
324 int sent;
325
326 intf = cons->intf;
327
328 xencons_lock_assert(cons);
329
330 wcons = intf->out_cons;
331 wprod = intf->out_prod;
332
333 mb();
334 KASSERT((wprod - wcons) <= sizeof(intf->out),
335 ("console send ring inconsistent"));
336
337 for (sent = 0; sent < size; sent++, wprod++) {
338 if ((wprod - wcons) >= sizeof(intf->out))
339 break;
340 intf->out[MASK_XENCONS_IDX(wprod, intf->out)] = buffer[sent];
341 }
342
343 wmb();
344 intf->out_prod = wprod;
345
346 xencons_notify_ring(cons);
347
348 return (sent);
349 }
350
351 static int
352 xencons_read_ring(struct xencons_priv *cons, char *buffer, unsigned int size)
353 {
354 struct xencons_interface *intf;
355 XENCONS_RING_IDX rcons, rprod;
356 unsigned int rsz;
357
358 intf = cons->intf;
359
360 xencons_lock_assert(cons);
361
362 rcons = intf->in_cons;
363 rprod = intf->in_prod;
364 rmb();
365
366 for (rsz = 0; rsz < size; rsz++, rcons++) {
367 if (rprod == rcons)
368 break;
369 buffer[rsz] = intf->in[MASK_XENCONS_IDX(rcons, intf->in)];
370 }
371
372 wmb();
373 intf->in_cons = rcons;
374
375 /* No need to notify the backend if nothing has been read */
376 if (rsz != 0)
377 xencons_notify_ring(cons);
378
379 return (rsz);
380 }
381
382 static const struct xencons_ops xencons_ring_ops = {
383 .early_init = xencons_early_init_ring,
384 .init = xencons_init_ring,
385 .read = xencons_read_ring,
386 .write = xencons_write_ring,
387 };
388
389 /*------------------ Common implementation of the console -------------------*/
390
391 /*
392 * Called by the low-level driver during early boot to initialize the
393 * main console driver.
394 * Only the minimal set up to get a console should be done here.
395 */
396 static void
397 xencons_early_init(void)
398 {
399
400 mtx_init(&main_cons.mtx, "XCONS LOCK", NULL, MTX_SPIN);
401
402 if (xen_get_console_evtchn() == 0)
403 main_cons.ops = &xencons_hypervisor_ops;
404 else
405 main_cons.ops = &xencons_ring_ops;
406
407 main_cons.ops->early_init(&main_cons);
408 }
409
410 /*
411 * Receive character from the console and put them in the internal buffer
412 * XXX: Handle overflow of the internal buffer
413 */
414 static void
415 xencons_rx(struct xencons_priv *cons)
416 {
417 char buf[16];
418 int sz;
419
420 xencons_lock(cons);
421 while ((sz = cons->ops->read(cons, buf, sizeof(buf))) > 0) {
422 int i;
423
424 for (i = 0; i < sz; i++)
425 cons->rbuf[RBUF_MASK(cons->rp++)] = buf[i];
426 }
427 xencons_unlock(cons);
428 }
429
430 /* Return true if the write buffer is full */
431 static bool
432 xencons_tx_full(struct xencons_priv *cons)
433 {
434 unsigned int used;
435
436 xencons_lock(cons);
437 used = cons->wp - cons->wc;
438 xencons_unlock(cons);
439
440 return (used >= WBUF_SIZE);
441 }
442
443 static void
444 xencons_tx_flush(struct xencons_priv *cons, int force)
445 {
446 int sz;
447
448 xencons_lock(cons);
449 while (cons->wc != cons->wp) {
450 int sent;
451 sz = cons->wp - cons->wc;
452 if (sz > (WBUF_SIZE - WBUF_MASK(cons->wc)))
453 sz = WBUF_SIZE - WBUF_MASK(cons->wc);
454 sent = cons->ops->write(cons, &cons->wbuf[WBUF_MASK(cons->wc)],
455 sz);
456
457 /*
458 * The other end may not have been initialized. Ignore
459 * the force.
460 */
461 if (__predict_false(sent < 0))
462 break;
463
464 /*
465 * If force is set, spin until the console data is
466 * flushed through the domain controller.
467 */
468 if (sent == 0 && __predict_true(!force))
469 break;
470
471 cons->wc += sent;
472 }
473 xencons_unlock(cons);
474 }
475
476 static bool
477 xencons_putc(struct xencons_priv *cons, int c, bool force_flush)
478 {
479
480 xencons_lock(cons);
481 if ((cons->wp - cons->wc) < WBUF_SIZE)
482 cons->wbuf[WBUF_MASK(cons->wp++)] = c;
483 xencons_unlock(cons);
484
485 xencons_tx_flush(cons, force_flush);
486
487 return (xencons_tx_full(cons));
488 }
489
490 static int
491 xencons_getc(struct xencons_priv *cons)
492 {
493 int ret;
494
495 xencons_lock(cons);
496 if (cons->rp != cons->rc) {
497 /* We need to return only one char */
498 ret = (int)cons->rbuf[RBUF_MASK(cons->rc)];
499 cons->rc++;
500 } else {
501 ret = -1;
502 }
503
504 xencons_unlock(cons);
505
506 return (ret);
507 }
508
509 static bool
510 xencons_tx(struct tty *tp)
511 {
512 bool cons_full;
513 char c;
514 struct xencons_priv *cons;
515
516 cons = tty_softc(tp);
517
518 tty_assert_locked(tp);
519
520 /*
521 * Don't transmit any character if the buffer is full. Otherwise,
522 * characters may be lost
523 */
524 if (xencons_tx_full(cons))
525 return (false);
526
527 cons_full = false;
528 while (!cons_full && ttydisc_getc(tp, &c, 1) == 1)
529 cons_full = xencons_putc(cons, c, false);
530
531 return (!cons_full);
532 }
533
534 static void
535 xencons_intr(void *arg)
536 {
537 struct tty *tp;
538 struct xencons_priv *cons;
539 int ret;
540
541 tp = arg;
542 cons = tty_softc(tp);
543
544 /*
545 * The input will be used by the low-level console when KDB is active
546 */
547 if (kdb_active)
548 return;
549
550 /*
551 * It's not necessary to retrieve input when the tty is not opened
552 */
553 if (!cons->opened)
554 return;
555
556 xencons_rx(cons);
557
558 tty_lock(tp);
559 while ((ret = xencons_getc(cons)) != -1) {
560 #ifdef KDB
561 kdb_alt_break(ret, &cons->altbrk);
562 #endif
563 ttydisc_rint(tp, ret, 0);
564 }
565 ttydisc_rint_done(tp);
566 tty_unlock(tp);
567
568 /* Try to flush remaining characters if necessary */
569 xencons_tx_flush(cons, 0);
570 }
571
572 /*
573 * Helpers to call while shutting down:
574 * - Force flush all output
575 */
576 static void
577 xencons_shutdown(void *arg, int howto)
578 {
579 struct tty *tp;
580
581 tp = arg;
582
583 xencons_tx_flush(tty_softc(tp), 1);
584 }
585
586 /*---------------------- Low-level console driver ---------------------------*/
587 static void
588 xencons_cnprobe(struct consdev *cp)
589 {
590
591 if (!xen_domain())
592 return;
593
594 cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
595 sprintf(cp->cn_name, "%s0", driver_name);
596 }
597
598 static void
599 xencons_cninit(struct consdev *cp)
600 {
601
602 xencons_early_init();
603 }
604
605 static void
606 xencons_cnterm(struct consdev *cp)
607 {
608 }
609
610 static void
611 xencons_cngrab(struct consdev *cp)
612 {
613 }
614
615 static void
616 xencons_cnungrab(struct consdev *cp)
617 {
618 }
619
620 static int
621 xencons_cngetc(struct consdev *dev)
622 {
623
624 xencons_rx(&main_cons);
625
626 return (xencons_getc(&main_cons));
627 }
628
629 static void
630 xencons_cnputc(struct consdev *dev, int c)
631 {
632 /*
633 * The low-level console is used by KDB and panic. We have to ensure
634 * that any character sent will be seen by the backend.
635 */
636 xencons_putc(&main_cons, c, true);
637 }
638
639 CONSOLE_DRIVER(xencons);
640
641 /*----------------------------- TTY driver ---------------------------------*/
642
643 static int
644 xencons_tty_open(struct tty *tp)
645 {
646 struct xencons_priv *cons;
647
648 cons = tty_softc(tp);
649
650 cons->opened = true;
651
652 return (0);
653 }
654
655 static void
656 xencons_tty_close(struct tty *tp)
657 {
658 struct xencons_priv *cons;
659
660 cons = tty_softc(tp);
661
662 cons->opened = false;
663 }
664
665 static void
666 xencons_timeout(void *v)
667 {
668 struct tty *tp;
669 struct xencons_priv *cons;
670
671 tp = v;
672 cons = tty_softc(tp);
673
674 if (!xencons_tx(tp))
675 callout_reset(&cons->callout, XC_POLLTIME,
676 xencons_timeout, tp);
677 }
678
679 static void
680 xencons_tty_outwakeup(struct tty *tp)
681 {
682 struct xencons_priv *cons;
683
684 cons = tty_softc(tp);
685
686 callout_stop(&cons->callout);
687
688 if (!xencons_tx(tp))
689 callout_reset(&cons->callout, XC_POLLTIME,
690 xencons_timeout, tp);
691 }
692
693 static struct ttydevsw xencons_ttydevsw = {
694 .tsw_flags = TF_NOPREFIX,
695 .tsw_open = xencons_tty_open,
696 .tsw_close = xencons_tty_close,
697 .tsw_outwakeup = xencons_tty_outwakeup,
698 };
699
700 /*------------------------ Main console driver ------------------------------*/
701 static void
702 xencons_identify(driver_t *driver, device_t parent)
703 {
704 device_t child __unused;
705
706 if (main_cons.ops == NULL)
707 return;
708
709 child = BUS_ADD_CHILD(parent, 0, driver_name, 0);
710 }
711
712 static int
713 xencons_probe(device_t dev)
714 {
715
716 device_set_desc(dev, "Xen Console");
717 return (BUS_PROBE_NOWILDCARD);
718 }
719
720 static int
721 xencons_attach(device_t dev)
722 {
723 struct tty *tp;
724 /*
725 * The main console is already allocated statically in order to
726 * support low-level console
727 */
728 struct xencons_priv *cons;
729 int err;
730
731 cons = &main_cons;
732
733 tp = tty_alloc(&xencons_ttydevsw, cons);
734 tty_makedev(tp, NULL, "%s%r", driver_name, 0);
735 device_set_softc(dev, tp);
736
737 callout_init_mtx(&cons->callout, tty_getlock(tp), 0);
738
739 err = cons->ops->init(dev, tp, xencons_intr);
740 if (err != 0) {
741 device_printf(dev, "Unable to initialize the console (%d)\n",
742 err);
743 return (err);
744 }
745
746 /* register handler to flush console on shutdown */
747 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, xencons_shutdown,
748 tp, SHUTDOWN_PRI_DEFAULT)) == NULL)
749 device_printf(dev, "shutdown event registration failed!\n");
750
751 return (0);
752 }
753
754 static int
755 xencons_resume(device_t dev)
756 {
757 struct xencons_priv *cons;
758 struct tty *tp;
759 int err;
760
761 tp = device_get_softc(dev);
762 cons = tty_softc(tp);
763 xen_intr_unbind(&cons->intr_handle);
764
765 err = cons->ops->init(dev, tp, xencons_intr);
766 if (err != 0) {
767 device_printf(dev, "Unable to resume the console (%d)\n", err);
768 return (err);
769 }
770
771 return (0);
772 }
773
774 static device_method_t xencons_methods[] = {
775 DEVMETHOD(device_identify, xencons_identify),
776 DEVMETHOD(device_probe, xencons_probe),
777 DEVMETHOD(device_attach, xencons_attach),
778 DEVMETHOD(device_resume, xencons_resume),
779
780 DEVMETHOD_END
781 };
782
783 static driver_t xencons_driver = {
784 driver_name,
785 xencons_methods,
786 0,
787 };
788
789 DRIVER_MODULE(xc, xenpv, xencons_driver, 0, 0);
Cache object: 379b22bd0453826c7823b21c939863fc
|