2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2014-2015
7 * Jan Kiszka <jan.kiszka@siemens.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "jailhouse.h"
18 #include <jailhouse/hypercall.h>
20 /* For compatibility with older kernel versions */
21 #include <linux/version.h>
23 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
24 #define DEVICE_ATTR_RO(_name) \
25 struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
28 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
29 static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,
32 struct kobj_attribute *kattr;
35 kattr = container_of(attr, struct kobj_attribute, attr);
37 ret = kattr->show(kobj, kattr, buf);
41 static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
42 const char *buf, size_t count)
44 struct kobj_attribute *kattr;
47 kattr = container_of(attr, struct kobj_attribute, attr);
49 ret = kattr->store(kobj, kattr, buf, count);
53 static const struct sysfs_ops cell_sysfs_ops = {
54 .show = kobj_attr_show,
55 .store = kobj_attr_store,
57 #define kobj_sysfs_ops cell_sysfs_ops
59 /* End of compatibility section - remove as version become obsolete */
61 static struct kobject *cells_dir;
63 struct jailhouse_cpu_stats_attr {
64 struct kobj_attribute kattr;
68 static ssize_t stats_show(struct kobject *kobj, struct kobj_attribute *attr,
71 struct jailhouse_cpu_stats_attr *stats_attr =
72 container_of(attr, struct jailhouse_cpu_stats_attr, kattr);
73 unsigned int code = JAILHOUSE_CPU_INFO_STAT_BASE + stats_attr->code;
74 struct cell *cell = container_of(kobj, struct cell, kobj);
75 unsigned long sum = 0;
79 for_each_cpu(cpu, &cell->cpus_assigned) {
80 value = jailhouse_call_arg2(JAILHOUSE_HC_CPU_GET_INFO, cpu,
86 return sprintf(buffer, "%lu\n", sum);
89 #define JAILHOUSE_CPU_STATS_ATTR(_name, _code) \
90 static struct jailhouse_cpu_stats_attr _name##_attr = { \
91 .kattr = __ATTR(_name, S_IRUGO, stats_show, NULL), \
95 JAILHOUSE_CPU_STATS_ATTR(vmexits_total, JAILHOUSE_CPU_STAT_VMEXITS_TOTAL);
96 JAILHOUSE_CPU_STATS_ATTR(vmexits_mmio, JAILHOUSE_CPU_STAT_VMEXITS_MMIO);
97 JAILHOUSE_CPU_STATS_ATTR(vmexits_management,
98 JAILHOUSE_CPU_STAT_VMEXITS_MANAGEMENT);
99 JAILHOUSE_CPU_STATS_ATTR(vmexits_hypercall,
100 JAILHOUSE_CPU_STAT_VMEXITS_HYPERCALL);
102 JAILHOUSE_CPU_STATS_ATTR(vmexits_pio, JAILHOUSE_CPU_STAT_VMEXITS_PIO);
103 JAILHOUSE_CPU_STATS_ATTR(vmexits_xapic, JAILHOUSE_CPU_STAT_VMEXITS_XAPIC);
104 JAILHOUSE_CPU_STATS_ATTR(vmexits_cr, JAILHOUSE_CPU_STAT_VMEXITS_CR);
105 JAILHOUSE_CPU_STATS_ATTR(vmexits_msr, JAILHOUSE_CPU_STAT_VMEXITS_MSR);
106 JAILHOUSE_CPU_STATS_ATTR(vmexits_cpuid, JAILHOUSE_CPU_STAT_VMEXITS_CPUID);
107 JAILHOUSE_CPU_STATS_ATTR(vmexits_xsetbv, JAILHOUSE_CPU_STAT_VMEXITS_XSETBV);
108 JAILHOUSE_CPU_STATS_ATTR(vmexits_exception,
109 JAILHOUSE_CPU_STAT_VMEXITS_EXCEPTION);
110 #elif defined(CONFIG_ARM)
111 JAILHOUSE_CPU_STATS_ATTR(vmexits_maintenance, JAILHOUSE_CPU_STAT_VMEXITS_MAINTENANCE);
112 JAILHOUSE_CPU_STATS_ATTR(vmexits_virt_irq, JAILHOUSE_CPU_STAT_VMEXITS_VIRQ);
113 JAILHOUSE_CPU_STATS_ATTR(vmexits_virt_sgi, JAILHOUSE_CPU_STAT_VMEXITS_VSGI);
116 static struct attribute *no_attrs[] = {
117 &vmexits_total_attr.kattr.attr,
118 &vmexits_mmio_attr.kattr.attr,
119 &vmexits_management_attr.kattr.attr,
120 &vmexits_hypercall_attr.kattr.attr,
122 &vmexits_pio_attr.kattr.attr,
123 &vmexits_xapic_attr.kattr.attr,
124 &vmexits_cr_attr.kattr.attr,
125 &vmexits_msr_attr.kattr.attr,
126 &vmexits_cpuid_attr.kattr.attr,
127 &vmexits_xsetbv_attr.kattr.attr,
128 &vmexits_exception_attr.kattr.attr,
129 #elif defined(CONFIG_ARM)
130 &vmexits_maintenance_attr.kattr.attr,
131 &vmexits_virt_irq_attr.kattr.attr,
132 &vmexits_virt_sgi_attr.kattr.attr,
137 static struct attribute_group stats_attr_group = {
142 static ssize_t id_show(struct kobject *kobj, struct kobj_attribute *attr,
145 struct cell *cell = container_of(kobj, struct cell, kobj);
147 return sprintf(buffer, "%u\n", cell->id);
150 static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
153 struct cell *cell = container_of(kobj, struct cell, kobj);
155 switch (jailhouse_call_arg1(JAILHOUSE_HC_CELL_GET_STATE, cell->id)) {
156 case JAILHOUSE_CELL_RUNNING:
157 return sprintf(buffer, "running\n");
158 case JAILHOUSE_CELL_RUNNING_LOCKED:
159 return sprintf(buffer, "running/locked\n");
160 case JAILHOUSE_CELL_SHUT_DOWN:
161 return sprintf(buffer, "shut down\n");
162 case JAILHOUSE_CELL_FAILED:
163 return sprintf(buffer, "failed\n");
165 return sprintf(buffer, "invalid\n");
169 static ssize_t cpus_assigned_show(struct kobject *kobj,
170 struct kobj_attribute *attr, char *buf)
172 struct cell *cell = container_of(kobj, struct cell, kobj);
175 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
176 written = scnprintf(buf, PAGE_SIZE, "%*pb\n",
177 cpumask_pr_args(&cell->cpus_assigned));
179 written = cpumask_scnprintf(buf, PAGE_SIZE, &cell->cpus_assigned);
180 written += scnprintf(buf + written, PAGE_SIZE - written, "\n");
185 static ssize_t cpus_failed_show(struct kobject *kobj,
186 struct kobj_attribute *attr, char *buf)
188 struct cell *cell = container_of(kobj, struct cell, kobj);
189 cpumask_var_t cpus_failed;
193 if (!zalloc_cpumask_var(&cpus_failed, GFP_KERNEL))
196 for_each_cpu(cpu, &cell->cpus_assigned)
197 if (jailhouse_call_arg2(JAILHOUSE_HC_CPU_GET_INFO, cpu,
198 JAILHOUSE_CPU_INFO_STATE) ==
199 JAILHOUSE_CPU_FAILED)
200 cpumask_set_cpu(cpu, cpus_failed);
202 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
203 written = scnprintf(buf, PAGE_SIZE, "%*pb\n",
204 cpumask_pr_args(cpus_failed));
206 written = cpumask_scnprintf(buf, PAGE_SIZE, cpus_failed);
207 written += scnprintf(buf + written, PAGE_SIZE - written, "\n");
210 free_cpumask_var(cpus_failed);
215 static struct kobj_attribute cell_id_attr = __ATTR_RO(id);
216 static struct kobj_attribute cell_state_attr = __ATTR_RO(state);
217 static struct kobj_attribute cell_cpus_assigned_attr =
218 __ATTR_RO(cpus_assigned);
219 static struct kobj_attribute cell_cpus_failed_attr = __ATTR_RO(cpus_failed);
221 static struct attribute *cell_attrs[] = {
223 &cell_state_attr.attr,
224 &cell_cpus_assigned_attr.attr,
225 &cell_cpus_failed_attr.attr,
229 static struct kobj_type cell_type = {
230 .release = jailhouse_cell_kobj_release,
231 .sysfs_ops = &kobj_sysfs_ops,
232 .default_attrs = cell_attrs,
235 int jailhouse_sysfs_cell_create(struct cell *cell, const char *name)
239 err = kobject_init_and_add(&cell->kobj, &cell_type, cells_dir, "%s",
242 jailhouse_cell_kobj_release(&cell->kobj);
246 err = sysfs_create_group(&cell->kobj, &stats_attr_group);
248 kobject_put(&cell->kobj);
255 void jailhouse_sysfs_cell_register(struct cell *cell)
257 kobject_uevent(&cell->kobj, KOBJ_ADD);
260 void jailhouse_sysfs_cell_delete(struct cell *cell)
262 sysfs_remove_group(&cell->kobj, &stats_attr_group);
263 kobject_put(&cell->kobj);
266 static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
269 return sprintf(buffer, "%d\n", jailhouse_enabled);
272 static ssize_t info_show(struct device *dev, char *buffer, unsigned int type)
277 if (mutex_lock_interruptible(&jailhouse_lock) != 0)
280 if (jailhouse_enabled)
281 val = jailhouse_call_arg1(JAILHOUSE_HC_HYPERVISOR_GET_INFO,
284 result = sprintf(buffer, "%ld\n", val);
288 mutex_unlock(&jailhouse_lock);
292 static ssize_t mem_pool_size_show(struct device *dev,
293 struct device_attribute *attr, char *buffer)
295 return info_show(dev, buffer, JAILHOUSE_INFO_MEM_POOL_SIZE);
298 static ssize_t mem_pool_used_show(struct device *dev,
299 struct device_attribute *attr, char *buffer)
301 return info_show(dev, buffer, JAILHOUSE_INFO_MEM_POOL_USED);
304 static ssize_t remap_pool_size_show(struct device *dev,
305 struct device_attribute *attr,
308 return info_show(dev, buffer, JAILHOUSE_INFO_REMAP_POOL_SIZE);
311 static ssize_t remap_pool_used_show(struct device *dev,
312 struct device_attribute *attr,
315 return info_show(dev, buffer, JAILHOUSE_INFO_REMAP_POOL_USED);
318 static DEVICE_ATTR_RO(enabled);
319 static DEVICE_ATTR_RO(mem_pool_size);
320 static DEVICE_ATTR_RO(mem_pool_used);
321 static DEVICE_ATTR_RO(remap_pool_size);
322 static DEVICE_ATTR_RO(remap_pool_used);
324 static struct attribute *jailhouse_sysfs_entries[] = {
325 &dev_attr_enabled.attr,
326 &dev_attr_mem_pool_size.attr,
327 &dev_attr_mem_pool_used.attr,
328 &dev_attr_remap_pool_size.attr,
329 &dev_attr_remap_pool_used.attr,
333 static struct attribute_group jailhouse_attribute_group = {
335 .attrs = jailhouse_sysfs_entries,
338 int jailhouse_sysfs_init(struct device *dev)
342 err = sysfs_create_group(&dev->kobj, &jailhouse_attribute_group);
346 cells_dir = kobject_create_and_add("cells", &dev->kobj);
348 sysfs_remove_group(&dev->kobj, &jailhouse_attribute_group);
355 void jailhouse_sysfs_exit(struct device *dev)
357 kobject_put(cells_dir);
358 sysfs_remove_group(&dev->kobj, &jailhouse_attribute_group);