1 /* 2 * xen console driver interface to hvc_console.c 3 * 4 * (c) 2007 Gerd Hoffmann <kraxel@suse.de> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <linux/console.h> 22 #include <linux/delay.h> 23 #include <linux/err.h> 24 #include <linux/irq.h> 25 #include <linux/init.h> 26 #include <linux/types.h> 27 #include <linux/list.h> 28 29 #include <asm/io.h> 30 #include <asm/xen/hypervisor.h> 31 32 #include <xen/xen.h> 33 #include <xen/interface/xen.h> 34 #include <xen/hvm.h> 35 #include <xen/grant_table.h> 36 #include <xen/page.h> 37 #include <xen/events.h> 38 #include <xen/interface/io/console.h> 39 #include <xen/interface/sched.h> 40 #include <xen/hvc-console.h> 41 #include <xen/xenbus.h> 42 43 #include "hvc_console.h" 44 45 #define HVC_COOKIE 0x58656e /* "Xen" in hex */ 46 47 struct xencons_info { 48 struct list_head list; 49 struct xenbus_device *xbdev; 50 struct xencons_interface *intf; 51 unsigned int evtchn; 52 struct hvc_struct *hvc; 53 int irq; 54 int vtermno; 55 grant_ref_t gntref; 56 }; 57 58 static LIST_HEAD(xenconsoles); 59 static DEFINE_SPINLOCK(xencons_lock); 60 61 /* ------------------------------------------------------------------ */ 62 63 static struct xencons_info *vtermno_to_xencons(int vtermno) 64 { 65 struct xencons_info *entry, *n, *ret = NULL; 66 67 if (list_empty(&xenconsoles)) 68 return NULL; 69 70 list_for_each_entry_safe(entry, n, &xenconsoles, list) { 71 if (entry->vtermno == vtermno) { 72 ret = entry; 73 break; 74 } 75 } 76 77 return ret; 78 } 79 80 static inline int xenbus_devid_to_vtermno(int devid) 81 { 82 return devid + HVC_COOKIE; 83 } 84 85 static inline void notify_daemon(struct xencons_info *cons) 86 { 87 /* Use evtchn: this is called early, before irq is set up. */ 88 notify_remote_via_evtchn(cons->evtchn); 89 } 90 91 static int __write_console(struct xencons_info *xencons, 92 const char *data, int len) 93 { 94 XENCONS_RING_IDX cons, prod; 95 struct xencons_interface *intf = xencons->intf; 96 int sent = 0; 97 98 cons = intf->out_cons; 99 prod = intf->out_prod; 100 mb(); /* update queue values before going on */ 101 BUG_ON((prod - cons) > sizeof(intf->out)); 102 103 while ((sent < len) && ((prod - cons) < sizeof(intf->out))) 104 intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; 105 106 wmb(); /* write ring before updating pointer */ 107 intf->out_prod = prod; 108 109 if (sent) 110 notify_daemon(xencons); 111 return sent; 112 } 113 114 static int domU_write_console(uint32_t vtermno, const char *data, int len) 115 { 116 int ret = len; 117 struct xencons_info *cons = vtermno_to_xencons(vtermno); 118 if (cons == NULL) 119 return -EINVAL; 120 121 /* 122 * Make sure the whole buffer is emitted, polling if 123 * necessary. We don't ever want to rely on the hvc daemon 124 * because the most interesting console output is when the 125 * kernel is crippled. 126 */ 127 while (len) { 128 int sent = __write_console(cons, data, len); 129 130 data += sent; 131 len -= sent; 132 133 if (unlikely(len)) 134 HYPERVISOR_sched_op(SCHEDOP_yield, NULL); 135 } 136 137 return ret; 138 } 139 140 static int domU_read_console(uint32_t vtermno, char *buf, int len) 141 { 142 struct xencons_interface *intf; 143 XENCONS_RING_IDX cons, prod; 144 int recv = 0; 145 struct xencons_info *xencons = vtermno_to_xencons(vtermno); 146 if (xencons == NULL) 147 return -EINVAL; 148 intf = xencons->intf; 149 150 cons = intf->in_cons; 151 prod = intf->in_prod; 152 mb(); /* get pointers before reading ring */ 153 BUG_ON((prod - cons) > sizeof(intf->in)); 154 155 while (cons != prod && recv < len) 156 buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)]; 157 158 mb(); /* read ring before consuming */ 159 intf->in_cons = cons; 160 161 notify_daemon(xencons); 162 return recv; 163 } 164 165 static struct hv_ops domU_hvc_ops = { 166 .get_chars = domU_read_console, 167 .put_chars = domU_write_console, 168 .notifier_add = notifier_add_irq, 169 .notifier_del = notifier_del_irq, 170 .notifier_hangup = notifier_hangup_irq, 171 }; 172 173 static int dom0_read_console(uint32_t vtermno, char *buf, int len) 174 { 175 return HYPERVISOR_console_io(CONSOLEIO_read, len, buf); 176 } 177 178 /* 179 * Either for a dom0 to write to the system console, or a domU with a 180 * debug version of Xen 181 */ 182 static int dom0_write_console(uint32_t vtermno, const char *str, int len) 183 { 184 int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str); 185 if (rc < 0) 186 return rc; 187 188 return len; 189 } 190 191 static struct hv_ops dom0_hvc_ops = { 192 .get_chars = dom0_read_console, 193 .put_chars = dom0_write_console, 194 .notifier_add = notifier_add_irq, 195 .notifier_del = notifier_del_irq, 196 .notifier_hangup = notifier_hangup_irq, 197 }; 198 199 static int xen_hvm_console_init(void) 200 { 201 int r; 202 uint64_t v = 0; 203 unsigned long gfn; 204 struct xencons_info *info; 205 206 if (!xen_hvm_domain()) 207 return -ENODEV; 208 209 info = vtermno_to_xencons(HVC_COOKIE); 210 if (!info) { 211 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); 212 if (!info) 213 return -ENOMEM; 214 } else if (info->intf != NULL) { 215 /* already configured */ 216 return 0; 217 } 218 /* 219 * If the toolstack (or the hypervisor) hasn't set these values, the 220 * default value is 0. Even though gfn = 0 and evtchn = 0 are 221 * theoretically correct values, in practice they never are and they 222 * mean that a legacy toolstack hasn't initialized the pv console correctly. 223 */ 224 r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); 225 if (r < 0 || v == 0) 226 goto err; 227 info->evtchn = v; 228 v = 0; 229 r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); 230 if (r < 0 || v == 0) 231 goto err; 232 gfn = v; 233 info->intf = xen_remap(gfn << XEN_PAGE_SHIFT, XEN_PAGE_SIZE); 234 if (info->intf == NULL) 235 goto err; 236 info->vtermno = HVC_COOKIE; 237 238 spin_lock(&xencons_lock); 239 list_add_tail(&info->list, &xenconsoles); 240 spin_unlock(&xencons_lock); 241 242 return 0; 243 err: 244 kfree(info); 245 return -ENODEV; 246 } 247 248 static int xen_pv_console_init(void) 249 { 250 struct xencons_info *info; 251 252 if (!xen_pv_domain()) 253 return -ENODEV; 254 255 if (!xen_start_info->console.domU.evtchn) 256 return -ENODEV; 257 258 info = vtermno_to_xencons(HVC_COOKIE); 259 if (!info) { 260 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); 261 if (!info) 262 return -ENOMEM; 263 } else if (info->intf != NULL) { 264 /* already configured */ 265 return 0; 266 } 267 info->evtchn = xen_start_info->console.domU.evtchn; 268 /* GFN == MFN for PV guest */ 269 info->intf = gfn_to_virt(xen_start_info->console.domU.mfn); 270 info->vtermno = HVC_COOKIE; 271 272 spin_lock(&xencons_lock); 273 list_add_tail(&info->list, &xenconsoles); 274 spin_unlock(&xencons_lock); 275 276 return 0; 277 } 278 279 static int xen_initial_domain_console_init(void) 280 { 281 struct xencons_info *info; 282 283 if (!xen_initial_domain()) 284 return -ENODEV; 285 286 info = vtermno_to_xencons(HVC_COOKIE); 287 if (!info) { 288 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); 289 if (!info) 290 return -ENOMEM; 291 } 292 293 info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false); 294 info->vtermno = HVC_COOKIE; 295 296 spin_lock(&xencons_lock); 297 list_add_tail(&info->list, &xenconsoles); 298 spin_unlock(&xencons_lock); 299 300 return 0; 301 } 302 303 static void xen_console_update_evtchn(struct xencons_info *info) 304 { 305 if (xen_hvm_domain()) { 306 uint64_t v = 0; 307 int err; 308 309 err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); 310 if (!err && v) 311 info->evtchn = v; 312 } else 313 info->evtchn = xen_start_info->console.domU.evtchn; 314 } 315 316 void xen_console_resume(void) 317 { 318 struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE); 319 if (info != NULL && info->irq) { 320 if (!xen_initial_domain()) 321 xen_console_update_evtchn(info); 322 rebind_evtchn_irq(info->evtchn, info->irq); 323 } 324 } 325 326 static void xencons_disconnect_backend(struct xencons_info *info) 327 { 328 if (info->irq > 0) 329 unbind_from_irqhandler(info->irq, NULL); 330 info->irq = 0; 331 if (info->evtchn > 0) 332 xenbus_free_evtchn(info->xbdev, info->evtchn); 333 info->evtchn = 0; 334 if (info->gntref > 0) 335 gnttab_free_grant_references(info->gntref); 336 info->gntref = 0; 337 if (info->hvc != NULL) 338 hvc_remove(info->hvc); 339 info->hvc = NULL; 340 } 341 342 static void xencons_free(struct xencons_info *info) 343 { 344 free_page((unsigned long)info->intf); 345 info->intf = NULL; 346 info->vtermno = 0; 347 kfree(info); 348 } 349 350 static int xen_console_remove(struct xencons_info *info) 351 { 352 xencons_disconnect_backend(info); 353 spin_lock(&xencons_lock); 354 list_del(&info->list); 355 spin_unlock(&xencons_lock); 356 if (info->xbdev != NULL) 357 xencons_free(info); 358 else { 359 if (xen_hvm_domain()) 360 iounmap(info->intf); 361 kfree(info); 362 } 363 return 0; 364 } 365 366 #ifdef CONFIG_HVC_XEN_FRONTEND 367 static int xencons_remove(struct xenbus_device *dev) 368 { 369 return xen_console_remove(dev_get_drvdata(&dev->dev)); 370 } 371 372 static int xencons_connect_backend(struct xenbus_device *dev, 373 struct xencons_info *info) 374 { 375 int ret, evtchn, devid, ref, irq; 376 struct xenbus_transaction xbt; 377 grant_ref_t gref_head; 378 379 ret = xenbus_alloc_evtchn(dev, &evtchn); 380 if (ret) 381 return ret; 382 info->evtchn = evtchn; 383 irq = bind_evtchn_to_irq(evtchn); 384 if (irq < 0) 385 return irq; 386 info->irq = irq; 387 devid = dev->nodename[strlen(dev->nodename) - 1] - '0'; 388 info->hvc = hvc_alloc(xenbus_devid_to_vtermno(devid), 389 irq, &domU_hvc_ops, 256); 390 if (IS_ERR(info->hvc)) 391 return PTR_ERR(info->hvc); 392 ret = gnttab_alloc_grant_references(1, &gref_head); 393 if (ret < 0) 394 return ret; 395 info->gntref = gref_head; 396 ref = gnttab_claim_grant_reference(&gref_head); 397 if (ref < 0) 398 return ref; 399 gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id, 400 virt_to_gfn(info->intf), 0); 401 402 again: 403 ret = xenbus_transaction_start(&xbt); 404 if (ret) { 405 xenbus_dev_fatal(dev, ret, "starting transaction"); 406 return ret; 407 } 408 ret = xenbus_printf(xbt, dev->nodename, "ring-ref", "%d", ref); 409 if (ret) 410 goto error_xenbus; 411 ret = xenbus_printf(xbt, dev->nodename, "port", "%u", 412 evtchn); 413 if (ret) 414 goto error_xenbus; 415 ret = xenbus_transaction_end(xbt, 0); 416 if (ret) { 417 if (ret == -EAGAIN) 418 goto again; 419 xenbus_dev_fatal(dev, ret, "completing transaction"); 420 return ret; 421 } 422 423 xenbus_switch_state(dev, XenbusStateInitialised); 424 return 0; 425 426 error_xenbus: 427 xenbus_transaction_end(xbt, 1); 428 xenbus_dev_fatal(dev, ret, "writing xenstore"); 429 return ret; 430 } 431 432 static int xencons_probe(struct xenbus_device *dev, 433 const struct xenbus_device_id *id) 434 { 435 int ret, devid; 436 struct xencons_info *info; 437 438 devid = dev->nodename[strlen(dev->nodename) - 1] - '0'; 439 if (devid == 0) 440 return -ENODEV; 441 442 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); 443 if (!info) 444 return -ENOMEM; 445 dev_set_drvdata(&dev->dev, info); 446 info->xbdev = dev; 447 info->vtermno = xenbus_devid_to_vtermno(devid); 448 info->intf = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); 449 if (!info->intf) 450 goto error_nomem; 451 452 ret = xencons_connect_backend(dev, info); 453 if (ret < 0) 454 goto error; 455 spin_lock(&xencons_lock); 456 list_add_tail(&info->list, &xenconsoles); 457 spin_unlock(&xencons_lock); 458 459 return 0; 460 461 error_nomem: 462 ret = -ENOMEM; 463 xenbus_dev_fatal(dev, ret, "allocating device memory"); 464 error: 465 xencons_disconnect_backend(info); 466 xencons_free(info); 467 return ret; 468 } 469 470 static int xencons_resume(struct xenbus_device *dev) 471 { 472 struct xencons_info *info = dev_get_drvdata(&dev->dev); 473 474 xencons_disconnect_backend(info); 475 memset(info->intf, 0, XEN_PAGE_SIZE); 476 return xencons_connect_backend(dev, info); 477 } 478 479 static void xencons_backend_changed(struct xenbus_device *dev, 480 enum xenbus_state backend_state) 481 { 482 switch (backend_state) { 483 case XenbusStateReconfiguring: 484 case XenbusStateReconfigured: 485 case XenbusStateInitialising: 486 case XenbusStateInitialised: 487 case XenbusStateUnknown: 488 break; 489 490 case XenbusStateInitWait: 491 break; 492 493 case XenbusStateConnected: 494 xenbus_switch_state(dev, XenbusStateConnected); 495 break; 496 497 case XenbusStateClosed: 498 if (dev->state == XenbusStateClosed) 499 break; 500 /* Missed the backend's CLOSING state -- fallthrough */ 501 case XenbusStateClosing: 502 xenbus_frontend_closed(dev); 503 break; 504 } 505 } 506 507 static const struct xenbus_device_id xencons_ids[] = { 508 { "console" }, 509 { "" } 510 }; 511 512 static struct xenbus_driver xencons_driver = { 513 .name = "xenconsole", 514 .ids = xencons_ids, 515 .probe = xencons_probe, 516 .remove = xencons_remove, 517 .resume = xencons_resume, 518 .otherend_changed = xencons_backend_changed, 519 }; 520 #endif /* CONFIG_HVC_XEN_FRONTEND */ 521 522 static int __init xen_hvc_init(void) 523 { 524 int r; 525 struct xencons_info *info; 526 const struct hv_ops *ops; 527 528 if (!xen_domain()) 529 return -ENODEV; 530 531 if (xen_initial_domain()) { 532 ops = &dom0_hvc_ops; 533 r = xen_initial_domain_console_init(); 534 if (r < 0) 535 return r; 536 info = vtermno_to_xencons(HVC_COOKIE); 537 } else { 538 ops = &domU_hvc_ops; 539 if (xen_hvm_domain()) 540 r = xen_hvm_console_init(); 541 else 542 r = xen_pv_console_init(); 543 if (r < 0) 544 return r; 545 546 info = vtermno_to_xencons(HVC_COOKIE); 547 info->irq = bind_evtchn_to_irq(info->evtchn); 548 } 549 if (info->irq < 0) 550 info->irq = 0; /* NO_IRQ */ 551 else 552 irq_set_noprobe(info->irq); 553 554 info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256); 555 if (IS_ERR(info->hvc)) { 556 r = PTR_ERR(info->hvc); 557 spin_lock(&xencons_lock); 558 list_del(&info->list); 559 spin_unlock(&xencons_lock); 560 if (info->irq) 561 unbind_from_irqhandler(info->irq, NULL); 562 kfree(info); 563 return r; 564 } 565 566 r = 0; 567 #ifdef CONFIG_HVC_XEN_FRONTEND 568 r = xenbus_register_frontend(&xencons_driver); 569 #endif 570 return r; 571 } 572 device_initcall(xen_hvc_init); 573 574 static int xen_cons_init(void) 575 { 576 const struct hv_ops *ops; 577 578 if (!xen_domain()) 579 return 0; 580 581 if (xen_initial_domain()) 582 ops = &dom0_hvc_ops; 583 else { 584 int r; 585 ops = &domU_hvc_ops; 586 587 if (xen_hvm_domain()) 588 r = xen_hvm_console_init(); 589 else 590 r = xen_pv_console_init(); 591 if (r < 0) 592 return r; 593 } 594 595 hvc_instantiate(HVC_COOKIE, 0, ops); 596 return 0; 597 } 598 console_initcall(xen_cons_init); 599 600 #ifdef CONFIG_EARLY_PRINTK 601 static void xenboot_write_console(struct console *console, const char *string, 602 unsigned len) 603 { 604 unsigned int linelen, off = 0; 605 const char *pos; 606 607 if (!xen_pv_domain()) 608 return; 609 610 dom0_write_console(0, string, len); 611 612 if (xen_initial_domain()) 613 return; 614 615 domU_write_console(0, "(early) ", 8); 616 while (off < len && NULL != (pos = strchr(string+off, '\n'))) { 617 linelen = pos-string+off; 618 if (off + linelen > len) 619 break; 620 domU_write_console(0, string+off, linelen); 621 domU_write_console(0, "\r\n", 2); 622 off += linelen + 1; 623 } 624 if (off < len) 625 domU_write_console(0, string+off, len-off); 626 } 627 628 struct console xenboot_console = { 629 .name = "xenboot", 630 .write = xenboot_write_console, 631 .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME, 632 .index = -1, 633 }; 634 #endif /* CONFIG_EARLY_PRINTK */ 635 636 void xen_raw_console_write(const char *str) 637 { 638 ssize_t len = strlen(str); 639 int rc = 0; 640 641 if (xen_domain()) { 642 rc = dom0_write_console(0, str, len); 643 #ifdef CONFIG_X86 644 if (rc == -ENOSYS && xen_hvm_domain()) 645 goto outb_print; 646 647 } else if (xen_cpuid_base()) { 648 int i; 649 outb_print: 650 for (i = 0; i < len; i++) 651 outb(str[i], 0xe9); 652 #endif 653 } 654 } 655 656 void xen_raw_printk(const char *fmt, ...) 657 { 658 static char buf[512]; 659 va_list ap; 660 661 va_start(ap, fmt); 662 vsnprintf(buf, sizeof(buf), fmt, ap); 663 va_end(ap); 664 665 xen_raw_console_write(buf); 666 } 667