Skip to content
Permalink
Browse files

driver: add console sysfs attribute

Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de>
[Jan: use double underscore for __jailhouse_console_dump_delta]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
  • Loading branch information...
rralf authored and jan-kiszka committed Jan 25, 2017
1 parent 705f57b commit 85972e517786b77cb3947238a82fabe10db8522f
Showing with 119 additions and 1 deletion.
  1. +3 −0 Documentation/sysfs-entries.txt
  2. +0 −1 TODO.md
  3. +94 −0 driver/main.c
  4. +2 −0 driver/main.h
  5. +20 −0 driver/sysfs.c
@@ -5,6 +5,7 @@ The following sysfs entries are provided by the Jailhouse Linux driver. These
can be used for monitoring the state of the hypervisor and its cells.

/sys/devices/jailhouse
|- console - hypervisor console (see [1])
|- enabled - 1 if Jailhouse is enabled, 0 otherwise
|- mem_pool_size - number of pages in hypervisor memory pool
|- mem_pool_used - used pages of hypervisor memory pool
@@ -30,3 +31,5 @@ may not reflect a fully consistent state. The existence and semantics of VM
exit reason values are architecture-dependent and may change in future
versions. In general statistics shall only be considered as a first hint when
analyzing cell behavior.

[1] Documentation/debug-output.md
@@ -89,7 +89,6 @@ Hardware error handling
Monitoring
- report error-triggering devices behind IOMMUs via sysfs
- hypervisor console via debugfs?
- cell software watchdog via comm region messages
-> time out pending comm region messages and kill failing cells
(includes timeouts of unanswered shutdown requests)
@@ -19,11 +19,13 @@
#include <linux/miscdevice.h>
#include <linux/firmware.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/uaccess.h>
#include <linux/reboot.h>
#include <linux/vmalloc.h>
#include <linux/io.h>
#include <asm/barrier.h>
#include <asm/smp.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -77,6 +79,8 @@ static void *hypervisor_mem;
static unsigned long hv_core_and_percpu_size;
static atomic_t call_done;
static int error_code;
static struct jailhouse_console* volatile console_page;
static bool console_available;

#ifdef CONFIG_X86
bool jailhouse_use_vmcall;
@@ -91,6 +95,23 @@ static void init_hypercall(void)
}
#endif

static void copy_console_page(struct jailhouse_console *dst)
{
unsigned int tail;

do {
/* spin while hypervisor is writing to console */
while (console_page->busy)
cpu_relax();
tail = console_page->tail;
rmb();

/* copy console page */
memcpy(dst, console_page, sizeof(struct jailhouse_console));
rmb();
} while (console_page->tail != tail || console_page->busy);
}

static long get_max_cpus(u32 cpu_set_size,
const struct jailhouse_system __user *system_config)
{
@@ -182,6 +203,73 @@ static inline const char * jailhouse_get_fw_name(void)
#endif
}

static int __jailhouse_console_dump_delta(struct jailhouse_console *console,
char *dst, unsigned int head,
unsigned int *miss)
{
int ret;
unsigned int head_mod, tail_mod;
unsigned int delta, missed = 0;

/* we might underflow here intentionally */
delta = console->tail - head;

/* check if we have misses */
if (delta > sizeof(console->content)) {
missed = delta - sizeof(console->content);
head = console->tail - sizeof(console->content);
delta = sizeof(console->content);
}

head_mod = head % sizeof(console->content);
tail_mod = console->tail % sizeof(console->content);

if (head_mod + delta > sizeof(console->content)) {
ret = sizeof(console->content) - head_mod;
memcpy(dst, console->content + head_mod, ret);
delta -= ret;
memcpy(dst + ret, console->content, delta);
ret += delta;
} else {
ret = delta;
memcpy(dst, console->content + head_mod, delta);
}

if (miss)
*miss = missed;

return ret;
}

int jailhouse_console_dump_delta(char *dst, unsigned int head,
unsigned int *miss)
{
int ret;
struct jailhouse_console *console;

if (!jailhouse_enabled)
return -EAGAIN;

if (!console_available)
return -EPERM;

console = kmalloc(sizeof(struct jailhouse_console), GFP_KERNEL);
if (console == NULL)
return -ENOMEM;

copy_console_page(console);
if (console->tail == head) {
ret = 0;
goto console_free_out;
}

ret = __jailhouse_console_dump_delta(console, dst, head, miss);

console_free_out:
kfree(console);
return ret;
}

/* See Documentation/bootstrap-interface.txt */
static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
{
@@ -273,6 +361,9 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
goto error_release_fw;
}

console_page = (struct jailhouse_console*)
(hypervisor_mem + header->console_page);

/* Copy hypervisor's binary image at beginning of the memory region
* and clear the rest to zero. */
memcpy(hypervisor_mem, hypervisor->data, hypervisor->size);
@@ -329,6 +420,9 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
}
#endif

console_available = CON2_TYPE(config->debug_console.flags) ==
JAILHOUSE_CON2_TYPE_ROOTPAGE;

err = jailhouse_cell_prepare_root(&config->root_cell);
if (err)
goto error_unmap;
@@ -22,5 +22,7 @@ extern bool jailhouse_enabled;

void *jailhouse_ioremap(phys_addr_t phys, unsigned long virt,
unsigned long size);
int jailhouse_console_dump_delta(char *dst, unsigned int head,
unsigned int *miss);

#endif /* !_JAILHOUSE_DRIVER_MAIN_H */
@@ -309,6 +309,24 @@ void jailhouse_sysfs_cell_delete(struct cell *cell)
kobject_put(&cell->kobj);
}

static ssize_t console_show(struct device *dev, struct device_attribute *attr,
char *buffer)
{
ssize_t ret;

if (mutex_lock_interruptible(&jailhouse_lock) != 0)
return -EINTR;

ret = jailhouse_console_dump_delta(buffer, 0, NULL);
/* don't return error if jailhouse is not enabled */
if (ret == -EAGAIN)
ret = 0;

mutex_unlock(&jailhouse_lock);

return ret;
}

static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
char *buffer)
{
@@ -361,13 +379,15 @@ static ssize_t remap_pool_used_show(struct device *dev,
return info_show(dev, buffer, JAILHOUSE_INFO_REMAP_POOL_USED);
}

static DEVICE_ATTR_RO(console);
static DEVICE_ATTR_RO(enabled);
static DEVICE_ATTR_RO(mem_pool_size);
static DEVICE_ATTR_RO(mem_pool_used);
static DEVICE_ATTR_RO(remap_pool_size);
static DEVICE_ATTR_RO(remap_pool_used);

static struct attribute *jailhouse_sysfs_entries[] = {
&dev_attr_console.attr,
&dev_attr_enabled.attr,
&dev_attr_mem_pool_size.attr,
&dev_attr_mem_pool_used.attr,

0 comments on commit 85972e5

Please sign in to comment.
You can’t perform that action at this time.