From: Sergiy Kibrik <[email protected]>
Committer: Nadav Har'El <[email protected]>
Branch: master
xenconsole: shared ring suport
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]>
Message-Id:
<[email protected]>
---
diff --git a/drivers/xenconsole.cc b/drivers/xenconsole.cc
--- 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
--- 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;
};
}
--
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.