Skip to content

Commit a0f60f8

Browse files
frankjaaborntraeger
authored andcommitted
s390/protvirt: Add sysfs firmware interface for Ultravisor information
That information, e.g. the maximum number of guests or installed Ultravisor facilities, is interesting for QEMU, Libvirt and administrators. Let's provide an easily parsable API to get that information. Signed-off-by: Janosch Frank <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Signed-off-by: Christian Borntraeger <[email protected]>
1 parent 084ea4d commit a0f60f8

File tree

1 file changed

+87
-0
lines changed
  • arch/s390/kernel

1 file changed

+87
-0
lines changed

arch/s390/kernel/uv.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,90 @@ int arch_make_page_accessible(struct page *page)
325325
EXPORT_SYMBOL_GPL(arch_make_page_accessible);
326326

327327
#endif
328+
329+
#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM)
330+
static ssize_t uv_query_facilities(struct kobject *kobj,
331+
struct kobj_attribute *attr, char *page)
332+
{
333+
return snprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n",
334+
uv_info.inst_calls_list[0],
335+
uv_info.inst_calls_list[1],
336+
uv_info.inst_calls_list[2],
337+
uv_info.inst_calls_list[3]);
338+
}
339+
340+
static struct kobj_attribute uv_query_facilities_attr =
341+
__ATTR(facilities, 0444, uv_query_facilities, NULL);
342+
343+
static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
344+
struct kobj_attribute *attr, char *page)
345+
{
346+
return snprintf(page, PAGE_SIZE, "%d\n",
347+
uv_info.max_guest_cpus);
348+
}
349+
350+
static struct kobj_attribute uv_query_max_guest_cpus_attr =
351+
__ATTR(max_cpus, 0444, uv_query_max_guest_cpus, NULL);
352+
353+
static ssize_t uv_query_max_guest_vms(struct kobject *kobj,
354+
struct kobj_attribute *attr, char *page)
355+
{
356+
return snprintf(page, PAGE_SIZE, "%d\n",
357+
uv_info.max_num_sec_conf);
358+
}
359+
360+
static struct kobj_attribute uv_query_max_guest_vms_attr =
361+
__ATTR(max_guests, 0444, uv_query_max_guest_vms, NULL);
362+
363+
static ssize_t uv_query_max_guest_addr(struct kobject *kobj,
364+
struct kobj_attribute *attr, char *page)
365+
{
366+
return snprintf(page, PAGE_SIZE, "%lx\n",
367+
uv_info.max_sec_stor_addr);
368+
}
369+
370+
static struct kobj_attribute uv_query_max_guest_addr_attr =
371+
__ATTR(max_address, 0444, uv_query_max_guest_addr, NULL);
372+
373+
static struct attribute *uv_query_attrs[] = {
374+
&uv_query_facilities_attr.attr,
375+
&uv_query_max_guest_cpus_attr.attr,
376+
&uv_query_max_guest_vms_attr.attr,
377+
&uv_query_max_guest_addr_attr.attr,
378+
NULL,
379+
};
380+
381+
static struct attribute_group uv_query_attr_group = {
382+
.attrs = uv_query_attrs,
383+
};
384+
385+
static struct kset *uv_query_kset;
386+
static struct kobject *uv_kobj;
387+
388+
static int __init uv_info_init(void)
389+
{
390+
int rc = -ENOMEM;
391+
392+
if (!test_facility(158))
393+
return 0;
394+
395+
uv_kobj = kobject_create_and_add("uv", firmware_kobj);
396+
if (!uv_kobj)
397+
return -ENOMEM;
398+
399+
uv_query_kset = kset_create_and_add("query", NULL, uv_kobj);
400+
if (!uv_query_kset)
401+
goto out_kobj;
402+
403+
rc = sysfs_create_group(&uv_query_kset->kobj, &uv_query_attr_group);
404+
if (!rc)
405+
return 0;
406+
407+
kset_unregister(uv_query_kset);
408+
out_kobj:
409+
kobject_del(uv_kobj);
410+
kobject_put(uv_kobj);
411+
return rc;
412+
}
413+
device_initcall(uv_info_init);
414+
#endif

0 commit comments

Comments
 (0)