Signed-off-by: Ralf Ramsauer <[email protected]>
---
 Documentation/debug-output.md |  8 +++-
 driver/main.c                 | 89 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/Documentation/debug-output.md b/Documentation/debug-output.md
index 1c11ca18..5d0610a1 100644
--- a/Documentation/debug-output.md
+++ b/Documentation/debug-output.md
@@ -89,7 +89,13 @@ Hypervisor Console via sysfs
 
 If the debug console of root cell has the flag JAILHOUSE_CON2_TYPE_ROOTPAGE
 set, the hypervisor console is available through
-/sys/devices/jailhouse/console.
+/sys/devices/jailhouse/console.  Continuous reading of the hypervisor console
+is available through /dev/jailhouse.
+
+Example
+```
+cat /dev/jailhouse
+```
 
 Inmates
 -------
diff --git a/driver/main.c b/driver/main.c
index 8a4b929f..f98e63c6 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -69,6 +69,10 @@ MODULE_FIRMWARE(JAILHOUSE_FW_NAME);
 #endif
 MODULE_VERSION(JAILHOUSE_VERSION);
 
+struct console_userdata {
+       unsigned int head;
+};
+
 DEFINE_MUTEX(jailhouse_lock);
 bool jailhouse_enabled;
 
@@ -621,11 +625,96 @@ static long jailhouse_ioctl(struct file *file, unsigned 
int ioctl,
        return err;
 }
 
+static int jailhouse_console_open(struct inode *inode, struct file *file)
+{
+       struct console_userdata *user;
+
+       file->private_data = NULL;
+       user = kzalloc(sizeof(struct console_userdata), GFP_KERNEL);
+       if (!user)
+               return -ENOMEM;
+
+       file->private_data = user;
+       return 0;
+}
+
+static int jailhouse_console_release(struct inode *inode, struct file *file)
+{
+       struct console_userdata *user = file->private_data;
+       if (user)
+               kfree(user);
+       return 0;
+}
+
+static ssize_t jailhouse_console_read(struct file *file, char __user *out,
+                                     size_t size, loff_t *off)
+{
+       struct console_userdata *user = file->private_data;
+       char *content;
+       unsigned int miss;
+       int ret;
+
+       content = kmalloc(sizeof(console_page->content), GFP_KERNEL);
+       if (content == NULL)
+               return -ENOMEM;
+
+       /* wait for new data */
+       while (1) {
+               ret = jailhouse_console_page_delta(content, user->head, &miss);
+               if ((!ret || ret == -EAGAIN) && file->f_flags & O_NONBLOCK)
+                       goto console_free_out;
+
+               if (ret == -EAGAIN)
+                       /* Reset the user head, if jailhouse is not enabled. We
+                        * have to do this, as jailhouse might be reenabled and
+                        * the file handle was kept open in the meanwhile */
+                       user->head = 0;
+               else if (ret < 0)
+                       goto console_free_out;
+               else if (ret)
+                       break;
+
+               schedule_timeout(HZ / 10);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       goto console_free_out;
+               }
+       }
+
+       if (miss) {
+               /* If we missed anything, warn user. We will dump the actual
+                * content in the next call. */
+               ret = snprintf(content, sizeof(console_page->content),
+                              "NOTE: missing %u byte console log\n",
+                              miss);
+               user->head += miss;
+               if (size < ret)
+                       ret = size;
+       } else {
+               if (size < ret)
+                       ret = size;
+               user->head += ret;
+       }
+
+       if (copy_to_user(out, content, ret))
+               ret = -EFAULT;
+
+console_free_out:
+       set_current_state(TASK_RUNNING);
+       kfree(content);
+       return ret;
+}
+
+
 static const struct file_operations jailhouse_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = jailhouse_ioctl,
        .compat_ioctl = jailhouse_ioctl,
        .llseek = noop_llseek,
+       .open = jailhouse_console_open,
+       .release = jailhouse_console_release,
+       .read = jailhouse_console_read,
 };
 
 static struct miscdevice jailhouse_misc_dev = {
-- 
2.11.0

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" 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.

Reply via email to