Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * xen console driver interface to hvc_console.c
0004  *
0005  * (c) 2007 Gerd Hoffmann <kraxel@suse.de>
0006  */
0007 
0008 #include <linux/console.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 #include <linux/irq.h>
0012 #include <linux/init.h>
0013 #include <linux/types.h>
0014 #include <linux/list.h>
0015 #include <linux/serial_core.h>
0016 
0017 #include <asm/io.h>
0018 #include <asm/xen/hypervisor.h>
0019 
0020 #include <xen/xen.h>
0021 #include <xen/interface/xen.h>
0022 #include <xen/hvm.h>
0023 #include <xen/grant_table.h>
0024 #include <xen/page.h>
0025 #include <xen/events.h>
0026 #include <xen/interface/io/console.h>
0027 #include <xen/interface/sched.h>
0028 #include <xen/hvc-console.h>
0029 #include <xen/xenbus.h>
0030 
0031 #include "hvc_console.h"
0032 
0033 #define HVC_COOKIE   0x58656e /* "Xen" in hex */
0034 
0035 struct xencons_info {
0036     struct list_head list;
0037     struct xenbus_device *xbdev;
0038     struct xencons_interface *intf;
0039     unsigned int evtchn;
0040     XENCONS_RING_IDX out_cons;
0041     unsigned int out_cons_same;
0042     struct hvc_struct *hvc;
0043     int irq;
0044     int vtermno;
0045     grant_ref_t gntref;
0046 };
0047 
0048 static LIST_HEAD(xenconsoles);
0049 static DEFINE_SPINLOCK(xencons_lock);
0050 
0051 /* ------------------------------------------------------------------ */
0052 
0053 static struct xencons_info *vtermno_to_xencons(int vtermno)
0054 {
0055     struct xencons_info *entry, *n, *ret = NULL;
0056 
0057     if (list_empty(&xenconsoles))
0058             return NULL;
0059 
0060     list_for_each_entry_safe(entry, n, &xenconsoles, list) {
0061         if (entry->vtermno == vtermno) {
0062             ret  = entry;
0063             break;
0064         }
0065     }
0066 
0067     return ret;
0068 }
0069 
0070 static inline int xenbus_devid_to_vtermno(int devid)
0071 {
0072     return devid + HVC_COOKIE;
0073 }
0074 
0075 static inline void notify_daemon(struct xencons_info *cons)
0076 {
0077     /* Use evtchn: this is called early, before irq is set up. */
0078     notify_remote_via_evtchn(cons->evtchn);
0079 }
0080 
0081 static int __write_console(struct xencons_info *xencons,
0082         const char *data, int len)
0083 {
0084     XENCONS_RING_IDX cons, prod;
0085     struct xencons_interface *intf = xencons->intf;
0086     int sent = 0;
0087 
0088     cons = intf->out_cons;
0089     prod = intf->out_prod;
0090     mb();           /* update queue values before going on */
0091 
0092     if ((prod - cons) > sizeof(intf->out)) {
0093         pr_err_once("xencons: Illegal ring page indices");
0094         return -EINVAL;
0095     }
0096 
0097     while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
0098         intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
0099 
0100     wmb();          /* write ring before updating pointer */
0101     intf->out_prod = prod;
0102 
0103     if (sent)
0104         notify_daemon(xencons);
0105     return sent;
0106 }
0107 
0108 static int domU_write_console(uint32_t vtermno, const char *data, int len)
0109 {
0110     int ret = len;
0111     struct xencons_info *cons = vtermno_to_xencons(vtermno);
0112     if (cons == NULL)
0113         return -EINVAL;
0114 
0115     /*
0116      * Make sure the whole buffer is emitted, polling if
0117      * necessary.  We don't ever want to rely on the hvc daemon
0118      * because the most interesting console output is when the
0119      * kernel is crippled.
0120      */
0121     while (len) {
0122         int sent = __write_console(cons, data, len);
0123 
0124         if (sent < 0)
0125             return sent;
0126 
0127         data += sent;
0128         len -= sent;
0129 
0130         if (unlikely(len))
0131             HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
0132     }
0133 
0134     return ret;
0135 }
0136 
0137 static int domU_read_console(uint32_t vtermno, char *buf, int len)
0138 {
0139     struct xencons_interface *intf;
0140     XENCONS_RING_IDX cons, prod;
0141     int recv = 0;
0142     struct xencons_info *xencons = vtermno_to_xencons(vtermno);
0143     unsigned int eoiflag = 0;
0144 
0145     if (xencons == NULL)
0146         return -EINVAL;
0147     intf = xencons->intf;
0148 
0149     cons = intf->in_cons;
0150     prod = intf->in_prod;
0151     mb();           /* get pointers before reading ring */
0152 
0153     if ((prod - cons) > sizeof(intf->in)) {
0154         pr_err_once("xencons: Illegal ring page indices");
0155         return -EINVAL;
0156     }
0157 
0158     while (cons != prod && recv < len)
0159         buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
0160 
0161     mb();           /* read ring before consuming */
0162     intf->in_cons = cons;
0163 
0164     /*
0165      * When to mark interrupt having been spurious:
0166      * - there was no new data to be read, and
0167      * - the backend did not consume some output bytes, and
0168      * - the previous round with no read data didn't see consumed bytes
0169      *   (we might have a race with an interrupt being in flight while
0170      *   updating xencons->out_cons, so account for that by allowing one
0171      *   round without any visible reason)
0172      */
0173     if (intf->out_cons != xencons->out_cons) {
0174         xencons->out_cons = intf->out_cons;
0175         xencons->out_cons_same = 0;
0176     }
0177     if (recv) {
0178         notify_daemon(xencons);
0179     } else if (xencons->out_cons_same++ > 1) {
0180         eoiflag = XEN_EOI_FLAG_SPURIOUS;
0181     }
0182 
0183     xen_irq_lateeoi(xencons->irq, eoiflag);
0184 
0185     return recv;
0186 }
0187 
0188 static const struct hv_ops domU_hvc_ops = {
0189     .get_chars = domU_read_console,
0190     .put_chars = domU_write_console,
0191     .notifier_add = notifier_add_irq,
0192     .notifier_del = notifier_del_irq,
0193     .notifier_hangup = notifier_hangup_irq,
0194 };
0195 
0196 static int dom0_read_console(uint32_t vtermno, char *buf, int len)
0197 {
0198     return HYPERVISOR_console_io(CONSOLEIO_read, len, buf);
0199 }
0200 
0201 /*
0202  * Either for a dom0 to write to the system console, or a domU with a
0203  * debug version of Xen
0204  */
0205 static int dom0_write_console(uint32_t vtermno, const char *str, int len)
0206 {
0207     int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
0208     if (rc < 0)
0209         return rc;
0210 
0211     return len;
0212 }
0213 
0214 static const struct hv_ops dom0_hvc_ops = {
0215     .get_chars = dom0_read_console,
0216     .put_chars = dom0_write_console,
0217     .notifier_add = notifier_add_irq,
0218     .notifier_del = notifier_del_irq,
0219     .notifier_hangup = notifier_hangup_irq,
0220 };
0221 
0222 static int xen_hvm_console_init(void)
0223 {
0224     int r;
0225     uint64_t v = 0;
0226     unsigned long gfn;
0227     struct xencons_info *info;
0228 
0229     if (!xen_hvm_domain())
0230         return -ENODEV;
0231 
0232     info = vtermno_to_xencons(HVC_COOKIE);
0233     if (!info) {
0234         info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
0235         if (!info)
0236             return -ENOMEM;
0237     } else if (info->intf != NULL) {
0238         /* already configured */
0239         return 0;
0240     }
0241     /*
0242      * If the toolstack (or the hypervisor) hasn't set these values, the
0243      * default value is 0. Even though gfn = 0 and evtchn = 0 are
0244      * theoretically correct values, in practice they never are and they
0245      * mean that a legacy toolstack hasn't initialized the pv console correctly.
0246      */
0247     r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
0248     if (r < 0 || v == 0)
0249         goto err;
0250     info->evtchn = v;
0251     v = 0;
0252     r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
0253     if (r < 0 || v == 0)
0254         goto err;
0255     gfn = v;
0256     info->intf = memremap(gfn << XEN_PAGE_SHIFT, XEN_PAGE_SIZE, MEMREMAP_WB);
0257     if (info->intf == NULL)
0258         goto err;
0259     info->vtermno = HVC_COOKIE;
0260 
0261     spin_lock(&xencons_lock);
0262     list_add_tail(&info->list, &xenconsoles);
0263     spin_unlock(&xencons_lock);
0264 
0265     return 0;
0266 err:
0267     kfree(info);
0268     return -ENODEV;
0269 }
0270 
0271 static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
0272 {
0273     info->evtchn = xen_start_info->console.domU.evtchn;
0274     /* GFN == MFN for PV guest */
0275     info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
0276     info->vtermno = vtermno;
0277 
0278     list_add_tail(&info->list, &xenconsoles);
0279 
0280     return 0;
0281 }
0282 
0283 static int xen_pv_console_init(void)
0284 {
0285     struct xencons_info *info;
0286 
0287     if (!xen_pv_domain())
0288         return -ENODEV;
0289 
0290     if (!xen_start_info->console.domU.evtchn)
0291         return -ENODEV;
0292 
0293     info = vtermno_to_xencons(HVC_COOKIE);
0294     if (!info) {
0295         info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
0296         if (!info)
0297             return -ENOMEM;
0298     } else if (info->intf != NULL) {
0299         /* already configured */
0300         return 0;
0301     }
0302     spin_lock(&xencons_lock);
0303     xencons_info_pv_init(info, HVC_COOKIE);
0304     spin_unlock(&xencons_lock);
0305 
0306     return 0;
0307 }
0308 
0309 static int xen_initial_domain_console_init(void)
0310 {
0311     struct xencons_info *info;
0312 
0313     if (!xen_initial_domain())
0314         return -ENODEV;
0315 
0316     info = vtermno_to_xencons(HVC_COOKIE);
0317     if (!info) {
0318         info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
0319         if (!info)
0320             return -ENOMEM;
0321     }
0322 
0323     info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
0324     info->vtermno = HVC_COOKIE;
0325 
0326     spin_lock(&xencons_lock);
0327     list_add_tail(&info->list, &xenconsoles);
0328     spin_unlock(&xencons_lock);
0329 
0330     return 0;
0331 }
0332 
0333 static void xen_console_update_evtchn(struct xencons_info *info)
0334 {
0335     if (xen_hvm_domain()) {
0336         uint64_t v = 0;
0337         int err;
0338 
0339         err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
0340         if (!err && v)
0341             info->evtchn = v;
0342     } else
0343         info->evtchn = xen_start_info->console.domU.evtchn;
0344 }
0345 
0346 void xen_console_resume(void)
0347 {
0348     struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE);
0349     if (info != NULL && info->irq) {
0350         if (!xen_initial_domain())
0351             xen_console_update_evtchn(info);
0352         rebind_evtchn_irq(info->evtchn, info->irq);
0353     }
0354 }
0355 
0356 #ifdef CONFIG_HVC_XEN_FRONTEND
0357 static void xencons_disconnect_backend(struct xencons_info *info)
0358 {
0359     if (info->irq > 0)
0360         unbind_from_irqhandler(info->irq, NULL);
0361     info->irq = 0;
0362     if (info->evtchn > 0)
0363         xenbus_free_evtchn(info->xbdev, info->evtchn);
0364     info->evtchn = 0;
0365     if (info->gntref > 0)
0366         gnttab_free_grant_references(info->gntref);
0367     info->gntref = 0;
0368     if (info->hvc != NULL)
0369         hvc_remove(info->hvc);
0370     info->hvc = NULL;
0371 }
0372 
0373 static void xencons_free(struct xencons_info *info)
0374 {
0375     free_page((unsigned long)info->intf);
0376     info->intf = NULL;
0377     info->vtermno = 0;
0378     kfree(info);
0379 }
0380 
0381 static int xen_console_remove(struct xencons_info *info)
0382 {
0383     xencons_disconnect_backend(info);
0384     spin_lock(&xencons_lock);
0385     list_del(&info->list);
0386     spin_unlock(&xencons_lock);
0387     if (info->xbdev != NULL)
0388         xencons_free(info);
0389     else {
0390         if (xen_hvm_domain())
0391             iounmap(info->intf);
0392         kfree(info);
0393     }
0394     return 0;
0395 }
0396 
0397 static int xencons_remove(struct xenbus_device *dev)
0398 {
0399     return xen_console_remove(dev_get_drvdata(&dev->dev));
0400 }
0401 
0402 static int xencons_connect_backend(struct xenbus_device *dev,
0403                   struct xencons_info *info)
0404 {
0405     int ret, evtchn, devid, ref, irq;
0406     struct xenbus_transaction xbt;
0407     grant_ref_t gref_head;
0408 
0409     ret = xenbus_alloc_evtchn(dev, &evtchn);
0410     if (ret)
0411         return ret;
0412     info->evtchn = evtchn;
0413     irq = bind_interdomain_evtchn_to_irq_lateeoi(dev, evtchn);
0414     if (irq < 0)
0415         return irq;
0416     info->irq = irq;
0417     devid = dev->nodename[strlen(dev->nodename) - 1] - '0';
0418     info->hvc = hvc_alloc(xenbus_devid_to_vtermno(devid),
0419             irq, &domU_hvc_ops, 256);
0420     if (IS_ERR(info->hvc))
0421         return PTR_ERR(info->hvc);
0422     ret = gnttab_alloc_grant_references(1, &gref_head);
0423     if (ret < 0)
0424         return ret;
0425     info->gntref = gref_head;
0426     ref = gnttab_claim_grant_reference(&gref_head);
0427     if (ref < 0)
0428         return ref;
0429     gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id,
0430                     virt_to_gfn(info->intf), 0);
0431 
0432  again:
0433     ret = xenbus_transaction_start(&xbt);
0434     if (ret) {
0435         xenbus_dev_fatal(dev, ret, "starting transaction");
0436         return ret;
0437     }
0438     ret = xenbus_printf(xbt, dev->nodename, "ring-ref", "%d", ref);
0439     if (ret)
0440         goto error_xenbus;
0441     ret = xenbus_printf(xbt, dev->nodename, "port", "%u",
0442                 evtchn);
0443     if (ret)
0444         goto error_xenbus;
0445     ret = xenbus_transaction_end(xbt, 0);
0446     if (ret) {
0447         if (ret == -EAGAIN)
0448             goto again;
0449         xenbus_dev_fatal(dev, ret, "completing transaction");
0450         return ret;
0451     }
0452 
0453     xenbus_switch_state(dev, XenbusStateInitialised);
0454     return 0;
0455 
0456  error_xenbus:
0457     xenbus_transaction_end(xbt, 1);
0458     xenbus_dev_fatal(dev, ret, "writing xenstore");
0459     return ret;
0460 }
0461 
0462 static int xencons_probe(struct xenbus_device *dev,
0463                   const struct xenbus_device_id *id)
0464 {
0465     int ret, devid;
0466     struct xencons_info *info;
0467 
0468     devid = dev->nodename[strlen(dev->nodename) - 1] - '0';
0469     if (devid == 0)
0470         return -ENODEV;
0471 
0472     info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
0473     if (!info)
0474         return -ENOMEM;
0475     dev_set_drvdata(&dev->dev, info);
0476     info->xbdev = dev;
0477     info->vtermno = xenbus_devid_to_vtermno(devid);
0478     info->intf = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
0479     if (!info->intf)
0480         goto error_nomem;
0481 
0482     ret = xencons_connect_backend(dev, info);
0483     if (ret < 0)
0484         goto error;
0485     spin_lock(&xencons_lock);
0486     list_add_tail(&info->list, &xenconsoles);
0487     spin_unlock(&xencons_lock);
0488 
0489     return 0;
0490 
0491  error_nomem:
0492     ret = -ENOMEM;
0493     xenbus_dev_fatal(dev, ret, "allocating device memory");
0494  error:
0495     xencons_disconnect_backend(info);
0496     xencons_free(info);
0497     return ret;
0498 }
0499 
0500 static int xencons_resume(struct xenbus_device *dev)
0501 {
0502     struct xencons_info *info = dev_get_drvdata(&dev->dev);
0503 
0504     xencons_disconnect_backend(info);
0505     memset(info->intf, 0, XEN_PAGE_SIZE);
0506     return xencons_connect_backend(dev, info);
0507 }
0508 
0509 static void xencons_backend_changed(struct xenbus_device *dev,
0510                    enum xenbus_state backend_state)
0511 {
0512     switch (backend_state) {
0513     case XenbusStateReconfiguring:
0514     case XenbusStateReconfigured:
0515     case XenbusStateInitialising:
0516     case XenbusStateInitialised:
0517     case XenbusStateUnknown:
0518         break;
0519 
0520     case XenbusStateInitWait:
0521         break;
0522 
0523     case XenbusStateConnected:
0524         xenbus_switch_state(dev, XenbusStateConnected);
0525         break;
0526 
0527     case XenbusStateClosed:
0528         if (dev->state == XenbusStateClosed)
0529             break;
0530         fallthrough;    /* Missed the backend's CLOSING state */
0531     case XenbusStateClosing:
0532         xenbus_frontend_closed(dev);
0533         break;
0534     }
0535 }
0536 
0537 static const struct xenbus_device_id xencons_ids[] = {
0538     { "console" },
0539     { "" }
0540 };
0541 
0542 static struct xenbus_driver xencons_driver = {
0543     .name = "xenconsole",
0544     .ids = xencons_ids,
0545     .probe = xencons_probe,
0546     .remove = xencons_remove,
0547     .resume = xencons_resume,
0548     .otherend_changed = xencons_backend_changed,
0549     .not_essential = true,
0550 };
0551 #endif /* CONFIG_HVC_XEN_FRONTEND */
0552 
0553 static int __init xen_hvc_init(void)
0554 {
0555     int r;
0556     struct xencons_info *info;
0557     const struct hv_ops *ops;
0558 
0559     if (!xen_domain())
0560         return -ENODEV;
0561 
0562     if (xen_initial_domain()) {
0563         ops = &dom0_hvc_ops;
0564         r = xen_initial_domain_console_init();
0565         if (r < 0)
0566             return r;
0567         info = vtermno_to_xencons(HVC_COOKIE);
0568     } else {
0569         ops = &domU_hvc_ops;
0570         if (xen_hvm_domain())
0571             r = xen_hvm_console_init();
0572         else
0573             r = xen_pv_console_init();
0574         if (r < 0)
0575             return r;
0576 
0577         info = vtermno_to_xencons(HVC_COOKIE);
0578         info->irq = bind_evtchn_to_irq_lateeoi(info->evtchn);
0579     }
0580     if (info->irq < 0)
0581         info->irq = 0; /* NO_IRQ */
0582     else
0583         irq_set_noprobe(info->irq);
0584 
0585     info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256);
0586     if (IS_ERR(info->hvc)) {
0587         r = PTR_ERR(info->hvc);
0588         spin_lock(&xencons_lock);
0589         list_del(&info->list);
0590         spin_unlock(&xencons_lock);
0591         if (info->irq)
0592             unbind_from_irqhandler(info->irq, NULL);
0593         kfree(info);
0594         return r;
0595     }
0596 
0597     r = 0;
0598 #ifdef CONFIG_HVC_XEN_FRONTEND
0599     r = xenbus_register_frontend(&xencons_driver);
0600 #endif
0601     return r;
0602 }
0603 device_initcall(xen_hvc_init);
0604 
0605 static int xen_cons_init(void)
0606 {
0607     const struct hv_ops *ops;
0608 
0609     if (!xen_domain())
0610         return 0;
0611 
0612     if (xen_initial_domain())
0613         ops = &dom0_hvc_ops;
0614     else {
0615         int r;
0616         ops = &domU_hvc_ops;
0617 
0618         if (xen_hvm_domain())
0619             r = xen_hvm_console_init();
0620         else
0621             r = xen_pv_console_init();
0622         if (r < 0)
0623             return r;
0624     }
0625 
0626     hvc_instantiate(HVC_COOKIE, 0, ops);
0627     return 0;
0628 }
0629 console_initcall(xen_cons_init);
0630 
0631 #ifdef CONFIG_X86
0632 static void xen_hvm_early_write(uint32_t vtermno, const char *str, int len)
0633 {
0634     if (xen_cpuid_base())
0635         outsb(0xe9, str, len);
0636 }
0637 #else
0638 static void xen_hvm_early_write(uint32_t vtermno, const char *str, int len) { }
0639 #endif
0640 
0641 #ifdef CONFIG_EARLY_PRINTK
0642 static int __init xenboot_console_setup(struct console *console, char *string)
0643 {
0644     static struct xencons_info xenboot;
0645 
0646     if (xen_initial_domain() || !xen_pv_domain())
0647         return 0;
0648 
0649     return xencons_info_pv_init(&xenboot, 0);
0650 }
0651 
0652 static void xenboot_write_console(struct console *console, const char *string,
0653                   unsigned len)
0654 {
0655     unsigned int linelen, off = 0;
0656     const char *pos;
0657 
0658     if (dom0_write_console(0, string, len) >= 0)
0659         return;
0660 
0661     if (!xen_pv_domain()) {
0662         xen_hvm_early_write(0, string, len);
0663         return;
0664     }
0665 
0666     if (domU_write_console(0, "(early) ", 8) < 0)
0667         return;
0668     while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
0669         linelen = pos-string+off;
0670         if (off + linelen > len)
0671             break;
0672         domU_write_console(0, string+off, linelen);
0673         domU_write_console(0, "\r\n", 2);
0674         off += linelen + 1;
0675     }
0676     if (off < len)
0677         domU_write_console(0, string+off, len-off);
0678 }
0679 
0680 struct console xenboot_console = {
0681     .name       = "xenboot",
0682     .write      = xenboot_write_console,
0683     .setup      = xenboot_console_setup,
0684     .flags      = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
0685     .index      = -1,
0686 };
0687 #endif  /* CONFIG_EARLY_PRINTK */
0688 
0689 void xen_raw_console_write(const char *str)
0690 {
0691     ssize_t len = strlen(str);
0692     int rc = 0;
0693 
0694     if (xen_domain()) {
0695         rc = dom0_write_console(0, str, len);
0696         if (rc != -ENOSYS || !xen_hvm_domain())
0697             return;
0698     }
0699     xen_hvm_early_write(0, str, len);
0700 }
0701 
0702 void xen_raw_printk(const char *fmt, ...)
0703 {
0704     static char buf[512];
0705     va_list ap;
0706 
0707     va_start(ap, fmt);
0708     vsnprintf(buf, sizeof(buf), fmt, ap);
0709     va_end(ap);
0710 
0711     xen_raw_console_write(buf);
0712 }
0713 
0714 static void xenboot_earlycon_write(struct console *console,
0715                   const char *string,
0716                   unsigned len)
0717 {
0718     dom0_write_console(0, string, len);
0719 }
0720 
0721 static int __init xenboot_earlycon_setup(struct earlycon_device *device,
0722                         const char *opt)
0723 {
0724     device->con->write = xenboot_earlycon_write;
0725     return 0;
0726 }
0727 EARLYCON_DECLARE(xenboot, xenboot_earlycon_setup);