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 mfn; 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 mfn = 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 mfn = v; 233 info->intf = xen_remap(mfn << PAGE_SHIFT, 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 info->intf = mfn_to_virt(xen_start_info->console.domU.mfn); 269 info->vtermno = HVC_COOKIE; 270 271 spin_lock(&xencons_lock); 272 list_add_tail(&info->list, &xenconsoles); 273 spin_unlock(&xencons_lock); 274 275 return 0; 276 } 277 278 static int xen_initial_domain_console_init(void) 279 { 280 struct xencons_info *info; 281 282 if (!xen_initial_domain()) 283 return -ENODEV; 284 285 info = vtermno_to_xencons(HVC_COOKIE); 286 if (!info) { 287 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); 288 if (!info) 289 return -ENOMEM; 290 } 291 292 info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0); 293 info->vtermno = HVC_COOKIE; 294 295 spin_lock(&xencons_lock); 296 list_add_tail(&info->list, &xenconsoles); 297 spin_unlock(&xencons_lock); 298 299 return 0; 300 } 301 302 void xen_console_resume(void) 303 { 304 struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE); 305 if (info != NULL && info->irq) 306 rebind_evtchn_irq(info->evtchn, info->irq); 307 } 308 309 static void xencons_disconnect_backend(struct xencons_info *info) 310 { 311 if (info->irq > 0) 312 unbind_from_irqhandler(info->irq, NULL); 313 info->irq = 0; 314 if (info->evtchn > 0) 315 xenbus_free_evtchn(info->xbdev, info->evtchn); 316 info->evtchn = 0; 317 if (info->gntref > 0) 318 gnttab_free_grant_references(info->gntref); 319 info->gntref = 0; 320 if (info->hvc != NULL) 321 hvc_remove(info->hvc); 322 info->hvc = NULL; 323 } 324 325 static void xencons_free(struct xencons_info *info) 326 { 327 free_page((unsigned long)info->intf); 328 info->intf = NULL; 329 info->vtermno = 0; 330 kfree(info); 331 } 332 333 static int xen_console_remove(struct xencons_info *info) 334 { 335 xencons_disconnect_backend(info); 336 spin_lock(&xencons_lock); 337 list_del(&info->list); 338 spin_unlock(&xencons_lock); 339 if (info->xbdev != NULL) 340 xencons_free(info); 341 else { 342 if (xen_hvm_domain()) 343 iounmap(info->intf); 344 kfree(info); 345 } 346 return 0; 347 } 348 349 #ifdef CONFIG_HVC_XEN_FRONTEND 350 static int xencons_remove(struct xenbus_device *dev) 351 { 352 return xen_console_remove(dev_get_drvdata(&dev->dev)); 353 } 354 355 static int xencons_connect_backend(struct xenbus_device *dev, 356 struct xencons_info *info) 357 { 358 int ret, evtchn, devid, ref, irq; 359 struct xenbus_transaction xbt; 360 grant_ref_t gref_head; 361 unsigned long mfn; 362 363 ret = xenbus_alloc_evtchn(dev, &evtchn); 364 if (ret) 365 return ret; 366 info->evtchn = evtchn; 367 irq = bind_evtchn_to_irq(evtchn); 368 if (irq < 0) 369 return irq; 370 info->irq = irq; 371 devid = dev->nodename[strlen(dev->nodename) - 1] - '0'; 372 info->hvc = hvc_alloc(xenbus_devid_to_vtermno(devid), 373 irq, &domU_hvc_ops, 256); 374 if (IS_ERR(info->hvc)) 375 return PTR_ERR(info->hvc); 376 if (xen_pv_domain()) 377 mfn = virt_to_mfn(info->intf); 378 else 379 mfn = __pa(info->intf) >> PAGE_SHIFT; 380 ret = gnttab_alloc_grant_references(1, &gref_head); 381 if (ret < 0) 382 return ret; 383 info->gntref = gref_head; 384 ref = gnttab_claim_grant_reference(&gref_head); 385 if (ref < 0) 386 return ref; 387 gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id, 388 mfn, 0); 389 390 again: 391 ret = xenbus_transaction_start(&xbt); 392 if (ret) { 393 xenbus_dev_fatal(dev, ret, "starting transaction"); 394 return ret; 395 } 396 ret = xenbus_printf(xbt, dev->nodename, "ring-ref", "%d", ref); 397 if (ret) 398 goto error_xenbus; 399 ret = xenbus_printf(xbt, dev->nodename, "port", "%u", 400 evtchn); 401 if (ret) 402 goto error_xenbus; 403 ret = xenbus_transaction_end(xbt, 0); 404 if (ret) { 405 if (ret == -EAGAIN) 406 goto again; 407 xenbus_dev_fatal(dev, ret, "completing transaction"); 408 return ret; 409 } 410 411 xenbus_switch_state(dev, XenbusStateInitialised); 412 return 0; 413 414 error_xenbus: 415 xenbus_transaction_end(xbt, 1); 416 xenbus_dev_fatal(dev, ret, "writing xenstore"); 417 return ret; 418 } 419 420 static int xencons_probe(struct xenbus_device *dev, 421 const struct xenbus_device_id *id) 422 { 423 int ret, devid; 424 struct xencons_info *info; 425 426 devid = dev->nodename[strlen(dev->nodename) - 1] - '0'; 427 if (devid == 0) 428 return -ENODEV; 429 430 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); 431 if (!info) 432 return -ENOMEM; 433 dev_set_drvdata(&dev->dev, info); 434 info->xbdev = dev; 435 info->vtermno = xenbus_devid_to_vtermno(devid); 436 info->intf = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); 437 if (!info->intf) 438 goto error_nomem; 439 440 ret = xencons_connect_backend(dev, info); 441 if (ret < 0) 442 goto error; 443 spin_lock(&xencons_lock); 444 list_add_tail(&info->list, &xenconsoles); 445 spin_unlock(&xencons_lock); 446 447 return 0; 448 449 error_nomem: 450 ret = -ENOMEM; 451 xenbus_dev_fatal(dev, ret, "allocating device memory"); 452 error: 453 xencons_disconnect_backend(info); 454 xencons_free(info); 455 return ret; 456 } 457 458 static int xencons_resume(struct xenbus_device *dev) 459 { 460 struct xencons_info *info = dev_get_drvdata(&dev->dev); 461 462 xencons_disconnect_backend(info); 463 memset(info->intf, 0, PAGE_SIZE); 464 return xencons_connect_backend(dev, info); 465 } 466 467 static void xencons_backend_changed(struct xenbus_device *dev, 468 enum xenbus_state backend_state) 469 { 470 switch (backend_state) { 471 case XenbusStateReconfiguring: 472 case XenbusStateReconfigured: 473 case XenbusStateInitialising: 474 case XenbusStateInitialised: 475 case XenbusStateUnknown: 476 break; 477 478 case XenbusStateInitWait: 479 break; 480 481 case XenbusStateConnected: 482 xenbus_switch_state(dev, XenbusStateConnected); 483 break; 484 485 case XenbusStateClosed: 486 if (dev->state == XenbusStateClosed) 487 break; 488 /* Missed the backend's CLOSING state -- fallthrough */ 489 case XenbusStateClosing: 490 xenbus_frontend_closed(dev); 491 break; 492 } 493 } 494 495 static const struct xenbus_device_id xencons_ids[] = { 496 { "console" }, 497 { "" } 498 }; 499 500 static struct xenbus_driver xencons_driver = { 501 .name = "xenconsole", 502 .ids = xencons_ids, 503 .probe = xencons_probe, 504 .remove = xencons_remove, 505 .resume = xencons_resume, 506 .otherend_changed = xencons_backend_changed, 507 }; 508 #endif /* CONFIG_HVC_XEN_FRONTEND */ 509 510 static int __init xen_hvc_init(void) 511 { 512 int r; 513 struct xencons_info *info; 514 const struct hv_ops *ops; 515 516 if (!xen_domain()) 517 return -ENODEV; 518 519 if (xen_initial_domain()) { 520 ops = &dom0_hvc_ops; 521 r = xen_initial_domain_console_init(); 522 if (r < 0) 523 return r; 524 info = vtermno_to_xencons(HVC_COOKIE); 525 } else { 526 ops = &domU_hvc_ops; 527 if (xen_hvm_domain()) 528 r = xen_hvm_console_init(); 529 else 530 r = xen_pv_console_init(); 531 if (r < 0) 532 return r; 533 534 info = vtermno_to_xencons(HVC_COOKIE); 535 info->irq = bind_evtchn_to_irq(info->evtchn); 536 } 537 if (info->irq < 0) 538 info->irq = 0; /* NO_IRQ */ 539 else 540 irq_set_noprobe(info->irq); 541 542 info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256); 543 if (IS_ERR(info->hvc)) { 544 r = PTR_ERR(info->hvc); 545 spin_lock(&xencons_lock); 546 list_del(&info->list); 547 spin_unlock(&xencons_lock); 548 if (info->irq) 549 unbind_from_irqhandler(info->irq, NULL); 550 kfree(info); 551 return r; 552 } 553 554 r = 0; 555 #ifdef CONFIG_HVC_XEN_FRONTEND 556 r = xenbus_register_frontend(&xencons_driver); 557 #endif 558 return r; 559 } 560 device_initcall(xen_hvc_init); 561 562 static int xen_cons_init(void) 563 { 564 const struct hv_ops *ops; 565 566 if (!xen_domain()) 567 return 0; 568 569 if (xen_initial_domain()) 570 ops = &dom0_hvc_ops; 571 else { 572 int r; 573 ops = &domU_hvc_ops; 574 575 if (xen_hvm_domain()) 576 r = xen_hvm_console_init(); 577 else 578 r = xen_pv_console_init(); 579 if (r < 0) 580 return r; 581 } 582 583 hvc_instantiate(HVC_COOKIE, 0, ops); 584 return 0; 585 } 586 console_initcall(xen_cons_init); 587 588 #ifdef CONFIG_EARLY_PRINTK 589 static void xenboot_write_console(struct console *console, const char *string, 590 unsigned len) 591 { 592 unsigned int linelen, off = 0; 593 const char *pos; 594 595 if (!xen_pv_domain()) 596 return; 597 598 dom0_write_console(0, string, len); 599 600 if (xen_initial_domain()) 601 return; 602 603 domU_write_console(0, "(early) ", 8); 604 while (off < len && NULL != (pos = strchr(string+off, '\n'))) { 605 linelen = pos-string+off; 606 if (off + linelen > len) 607 break; 608 domU_write_console(0, string+off, linelen); 609 domU_write_console(0, "\r\n", 2); 610 off += linelen + 1; 611 } 612 if (off < len) 613 domU_write_console(0, string+off, len-off); 614 } 615 616 struct console xenboot_console = { 617 .name = "xenboot", 618 .write = xenboot_write_console, 619 .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME, 620 .index = -1, 621 }; 622 #endif /* CONFIG_EARLY_PRINTK */ 623 624 void xen_raw_console_write(const char *str) 625 { 626 ssize_t len = strlen(str); 627 int rc = 0; 628 629 if (xen_domain()) { 630 rc = dom0_write_console(0, str, len); 631 #ifdef CONFIG_X86 632 if (rc == -ENOSYS && xen_hvm_domain()) 633 goto outb_print; 634 635 } else if (xen_cpuid_base()) { 636 int i; 637 outb_print: 638 for (i = 0; i < len; i++) 639 outb(str[i], 0xe9); 640 #endif 641 } 642 } 643 644 void xen_raw_printk(const char *fmt, ...) 645 { 646 static char buf[512]; 647 va_list ap; 648 649 va_start(ap, fmt); 650 vsnprintf(buf, sizeof(buf), fmt, ap); 651 va_end(ap); 652 653 xen_raw_console_write(buf); 654 } 655