]> xenbits.xensource.com Git - people/royger/xen-test-framework.git/commitdiff
PV Console driver. Synchronous output only
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 20 Mar 2015 23:30:35 +0000 (00:30 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 28 Sep 2015 13:53:02 +0000 (14:53 +0100)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
README
arch/x86/setup.c
common/console.c
include/xen/io/console.h [new file with mode: 0644]
include/xtf/atomic.h
include/xtf/console.h

diff --git a/README b/README
index 91c9ca8dfda3dbbdfaaf221f377d2895d3495605..c4f4192ffc4f604024edb964665fda3546f3006c 100644 (file)
--- a/README
+++ b/README
@@ -13,11 +13,11 @@ machine.
 
 * PV 32 and 64 bit entry points
 * Hypercall interface
+* PV console driver (output)
 
 ## TODO List:
 
 * More introductory text
 * Entry points for 32 and 64bit HVM guests
-* PV console driver
 * Common reporting framework
 * Tests
index 09669b7c8a1c60621ee45ea7f479e682c6cb7a95..a8f9138c2ab9c3d6becbc707f6815df3d14a01cb 100644 (file)
@@ -3,12 +3,26 @@
 #include <xtf/hypercall.h>
 
 #include <arch/x86/config.h>
+#include <arch/x86/mm.h>
 
 #ifdef CONFIG_ENV_pv
 /* Filled in by head_pv.S */
 start_info_t *start_info = NULL;
 #endif
 
+static void setup_pv_console(void)
+{
+    xencons_interface_t *cons_ring;
+    evtchn_port_t cons_evtchn;
+
+#if defined(CONFIG_ENV_pv)
+    cons_ring = mfn_to_virt(start_info->console.domU.mfn);
+    cons_evtchn = start_info->console.domU.evtchn;
+#endif
+
+    init_pv_console(cons_ring, cons_evtchn);
+}
+
 static void xen_console_write(const char *buf, size_t len)
 {
     hypercall_console_write(buf, len);
@@ -17,6 +31,8 @@ static void xen_console_write(const char *buf, size_t len)
 void arch_setup(void)
 {
     register_console_callback(xen_console_write);
+
+    setup_pv_console();
 }
 
 /*
index da68dbadd9ea8bef57a33c55e74db9a3ea588161..fe2551b22851f8ca828d22b71b190a94ac2138c6 100644 (file)
@@ -1,5 +1,7 @@
 #include <xtf/types.h>
+#include <xtf/atomic.h>
 #include <xtf/console.h>
+#include <xtf/hypercall.h>
 #include <xtf/lib.h>
 #include <xtf/libc.h>
 
@@ -7,16 +9,78 @@
  * Output functions, registered if/when available.
  * Possibilities:
  * - Xen hypervisor console
+ * - PV console
  */
-static cons_output_cb output_fns[1];
+static cons_output_cb output_fns[2];
 static unsigned int nr_cons_cb;
 
+/* Guest PV console details. */
+static xencons_interface_t *pv_ring;
+static evtchn_port_t pv_evtchn;
+
 void register_console_callback(cons_output_cb fn)
 {
     if ( nr_cons_cb < ARRAY_SIZE(output_fns) )
         output_fns[nr_cons_cb++] = fn;
 }
 
+/*
+ * Write some data into the pv ring, taking care not to overflow the ring.
+ */
+static size_t pv_console_write_some(const char *buf, size_t len)
+{
+    size_t s = 0;
+    uint32_t cons = LOAD_ACQUIRE(&pv_ring->out_cons), prod = pv_ring->out_prod;
+
+    while ( (s < len) && ((prod - cons) < sizeof(pv_ring->out)) )
+        pv_ring->out[prod++ & (sizeof(pv_ring->out) - 1)] = buf[s++];
+
+    STORE_RELEASE(&pv_ring->out_prod, prod);
+
+    return s;
+}
+
+/*
+ * Write some data into the pv ring, synchronously waiting for all data to be
+ * consumed.
+ */
+static void pv_console_write(const char *buf, size_t len)
+{
+    size_t written = 0;
+    uint32_t cons = LOAD_ACQUIRE(&pv_ring->out_cons);
+
+    do
+    {
+        /* Try and put some data into the ring. */
+        written = pv_console_write_some(&buf[written], len - written);
+
+        /* Kick xenconsoled into action. */
+        hypercall_evtchn_send(pv_evtchn);
+
+        /*
+         * If we have more to write, the ring must have filled up.  Wait for
+         * more space.
+         */
+        if ( written < len )
+        {
+            while ( ACCESS_ONCE(pv_ring->out_cons) == cons )
+                hypercall_yield();
+        }
+
+    } while ( written < len );
+
+    /* Wait for xenconsoled to consume all the data we gave. */
+    while ( ACCESS_ONCE(pv_ring->out_cons) != pv_ring->out_prod )
+        hypercall_yield();
+}
+
+void init_pv_console(xencons_interface_t *ring, evtchn_port_t port)
+{
+    pv_ring = ring;
+    pv_evtchn = port;
+    register_console_callback(pv_console_write);
+}
+
 void printk(const char *fmt, ...)
 {
     unsigned int i;
diff --git a/include/xen/io/console.h b/include/xen/io/console.h
new file mode 100644 (file)
index 0000000..5914833
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef XEN_PUBLIC_IO_CONSOLE_H
+#define XEN_PUBLIC_IO_CONSOLE_H
+
+struct xencons_interface
+{
+    char in[1024];
+    char out[2048];
+    uint32_t in_cons, in_prod;
+    uint32_t out_cons, out_prod;
+};
+typedef struct xencons_interface xencons_interface_t;
+
+#endif /* XEN_PUBLIC_IO_CONSOLE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 30341654dac2480f69763b187c41362a1093b26b..b28612afde20309db2b41e05bdb3151591b77421 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef XTF_ATOMIC_H
 #define XTF_ATOMIC_H
 
+#include <xtf/lib.h>
 #include <xtf/barrier.h>
 
 #define LOAD_ACQUIRE(p)                         \
index f6b2f944d5d4c5f1fe036c81f8c5b8c49ae35c40..e85236b8c0f4eb60a0e19be5169fbaa7b8f95a3a 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <xtf/compiler.h>
 
+#include <xen/event_channel.h>
+#include <xen/io/console.h>
+
 /* Console output callback. */
 typedef void (*cons_output_cb)(const char *buf, size_t len);
 
@@ -12,6 +15,12 @@ typedef void (*cons_output_cb)(const char *buf, size_t len);
  */
 void register_console_callback(cons_output_cb cb);
 
+/*
+ * Initialise the PV console.  Will register a callback.
+ */
+void init_pv_console(xencons_interface_t *ring,
+                     evtchn_port_t port);
+
 void printk(const char *fmt, ...) __printf(1, 2);
 
 #endif /* XTF_CONSOLE_H */