Complete driver to properly work with xl console utility, i.e. full read/write access. Driver is extended to work with shared structure (ring) and event channel.
Signed-off-by: Sergiy Kibrik <[email protected]> --- drivers/xenconsole.cc | 83 +++++++++++++++++++++++++++++++++++++++++++++++---- drivers/xenconsole.hh | 14 +++++++-- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/drivers/xenconsole.cc b/drivers/xenconsole.cc index fe7c5bf..92a76b6 100644 --- a/drivers/xenconsole.cc +++ b/drivers/xenconsole.cc @@ -5,32 +5,105 @@ * BSD license as described in the LICENSE file in the top-level directory. */ +#define XENHVM //FIXME hack to reveal hvm_get_parameter() #include <bsd/porting/netport.h> /* __dead2 defined here */ +#include <bsd/porting/bus.h> +#include <machine/xen/xen-os.h> #include <xen/hypervisor.h> - +#include <xen/interface/hvm/params.h> +#include <xen/interface/io/console.h> +#include <xen/xen_intr.h> +#include <xen/evtchn.h> +#include <osv/mmio.hh> #include "xenconsole.hh" namespace console { +XEN_Console:: +XEN_Console::XEN_Console() + : _interface(0) + , _evtchn(-1) + , _irq(0) + , _pfn(0) +{} + +void XEN_Console::handle_intr() +{ + _thread->wake(); +} + void XEN_Console::write(const char *str, size_t len) { - HYPERVISOR_console_write(str, len); + assert(len > 0); + if (!_interface) { + HYPERVISOR_console_write(str, len); + return; + } + + /* str might be larger then ring, so write it by chunks in this case */ + XENCONS_RING_IDX prod = _interface->out_prod; + constexpr auto ringsize = sizeof(_interface->out) - 1; + while (true) { + XENCONS_RING_IDX cons = _interface->out_cons; + auto delta = prod - cons; + + if (unlikely(delta > ringsize)) { + prod = cons; /* ring is corrupted, reset is the best we can do */ + delta = 0; + } + + size_t c = 0; + for (; c < std::min(ringsize - delta, len); c++) + _interface->out[MASK_XENCONS_IDX(prod++, _interface->out)] = *str++; + + _interface->out_prod = prod; + wmb(); + + if (likely(c == len)) + break; /* flush() will do evtchn notification */ + + len -= ringsize - delta; + notify_remote_via_evtchn(_evtchn); + + while (_interface->out_cons != _interface->out_prod) + cpu_relax(); /* can't sleep here */ + } } void XEN_Console::dev_start() { + _pfn = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN); + _evtchn = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN); + + if (!_pfn || !_evtchn) + throw std::runtime_error("fail to get console params"); + + if (bind_caller_port_to_irqhandler(_evtchn, "xenconsole", + XEN_Console::console_intr, + static_cast<void*>(this), + INTR_TYPE_MISC, &_irq) != 0) + throw std::runtime_error("fail to bind evtchn"); + + _interface = (xencons_interface*)mmio_map(_pfn << PAGE_SHIFT, PAGE_SIZE); } void XEN_Console::flush() { + notify_remote_via_evtchn(_evtchn); } bool XEN_Console::input_ready() { - return false; /*TODO: support input */ + return _interface->in_cons != _interface->in_prod; } char XEN_Console::readch() { - return '\0'; /*TODO: support input */ + XENCONS_RING_IDX cons; + char c; + assert(_interface); + cons = _interface->in_cons; + c = _interface->in[MASK_XENCONS_IDX(cons, _interface->in)]; + mb(); + _interface->in_cons = cons + 1; + return c; } - } diff --git a/drivers/xenconsole.hh b/drivers/xenconsole.hh index ec43893..ca6d8cf 100644 --- a/drivers/xenconsole.hh +++ b/drivers/xenconsole.hh @@ -9,13 +9,14 @@ #define XEN_CONSOLE_HH #include "console-driver.hh" -#include "exceptions.hh" -#include <osv/interrupt.hh> +#include <xen/interface/xen.h> +#include <xen/interface/grant_table.h> namespace console { class XEN_Console : public console_driver { public: + XEN_Console(); virtual void write(const char *str, size_t len); virtual void flush(); virtual bool input_ready(); @@ -24,6 +25,15 @@ public: private: virtual void dev_start(); virtual const char *thread_name() { return "xen-input"; } + void handle_intr(); + static void console_intr(void *arg) { + static_cast<XEN_Console*>(arg)->handle_intr(); + } + + struct xencons_interface *_interface; + int _evtchn; + unsigned int _irq; + unsigned long _pfn; }; } -- 2.7.4 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
