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.