Make the "used, dirty" firmware image visible in sysfs. The data segment contains data that could be useful for all sorts of debugging tools. This feature is introduced to extract code coverage information (gcov).
Signed-off-by: Henning Schild <[email protected]> diff --git a/driver/main.c b/driver/main.c --- a/driver/main.c +++ b/driver/main.c @@ -78,9 +78,10 @@ DEFINE_MUTEX(jailhouse_lock); bool jailhouse_enabled; +void *hypervisor_mem; +size_t hypervisor_size; static struct device *jailhouse_dev; -static void *hypervisor_mem; static unsigned long hv_core_and_percpu_size; static atomic_t call_done; static int error_code; @@ -277,8 +278,10 @@ static void jailhouse_firmware_free(void) { if (hypervisor_mem) { + jailhouse_sysfs_firmware_exit(jailhouse_dev); vunmap(hypervisor_mem); hypervisor_mem = NULL; + hypervisor_size = 0; } } @@ -417,6 +420,11 @@ header = (struct jailhouse_header *)hypervisor_mem; header->max_cpus = max_cpus; + hypervisor_size = hypervisor->size; + err = jailhouse_sysfs_firmware_init(jailhouse_dev); + if (err) + goto error_unmap; + /* * ARMv8 requires to clean D-cache and invalidate I-cache for memory * containing new instructions. On x86 this is a NOP. On ARMv7 the diff --git a/driver/main.h b/driver/main.h --- a/driver/main.h +++ b/driver/main.h @@ -19,6 +19,8 @@ extern struct mutex jailhouse_lock; extern bool jailhouse_enabled; +extern void *hypervisor_mem; +extern size_t hypervisor_size; void *jailhouse_ioremap(phys_addr_t phys, unsigned long virt, unsigned long size); diff --git a/driver/sysfs.c b/driver/sysfs.c --- a/driver/sysfs.c +++ b/driver/sysfs.c @@ -379,6 +379,29 @@ return info_show(dev, buffer, JAILHOUSE_INFO_REMAP_POOL_USED); } +static ssize_t firmware_show(struct file *filp, struct kobject *kobj, + struct bin_attribute *a, char *buf, loff_t off, + size_t count) +{ + if (mutex_lock_interruptible(&jailhouse_lock) != 0) + return -EINTR; + + if (jailhouse_enabled || + hypervisor_mem == NULL || hypervisor_size == 0) { + mutex_unlock(&jailhouse_lock); + return -EIO; + } + if (off >= hypervisor_size) { + count = 0; + } else { + if (off + count > hypervisor_size) + count = hypervisor_size - off; + memcpy(buf, hypervisor_mem + off, count); + } + mutex_unlock(&jailhouse_lock); + return count; +} + static DEVICE_ATTR_RO(console); static DEVICE_ATTR_RO(enabled); static DEVICE_ATTR_RO(mem_pool_size); @@ -401,6 +424,24 @@ .attrs = jailhouse_sysfs_entries, }; +static struct bin_attribute bin_attr_firmware = { + .attr.name = "jailhouse.bin", + .attr.mode = S_IRUSR, + .size = 0, + .read = firmware_show +}; + +int jailhouse_sysfs_firmware_init(struct device *dev) +{ + bin_attr_firmware.size = hypervisor_size; + return(sysfs_create_bin_file(&dev->kobj, &bin_attr_firmware)); +} + +void jailhouse_sysfs_firmware_exit(struct device *dev) +{ + sysfs_remove_bin_file(&dev->kobj, &bin_attr_firmware); +} + int jailhouse_sysfs_init(struct device *dev) { int err; diff --git a/driver/sysfs.h b/driver/sysfs.h --- a/driver/sysfs.h +++ b/driver/sysfs.h @@ -19,6 +19,8 @@ void jailhouse_sysfs_cell_register(struct cell *cell); void jailhouse_sysfs_cell_delete(struct cell *cell); +int jailhouse_sysfs_firmware_init(struct device *dev); +void jailhouse_sysfs_firmware_exit(struct device *dev); int jailhouse_sysfs_init(struct device *dev); void jailhouse_sysfs_exit(struct device *dev); -- 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.
