Skip to content

Commit 415dab3

Browse files
Per Bilsejgross1
authored andcommitted
drivers/xen/hypervisor: Expose Xen SIF flags to userspace
/proc/xen is a legacy pseudo filesystem which predates Xen support getting merged into Linux. It has largely been replaced with more normal locations for data (/sys/hypervisor/ for info, /dev/xen/ for user devices). We want to compile xenfs support out of the dom0 kernel. There is one item which only exists in /proc/xen, namely /proc/xen/capabilities with "control_d" being the signal of "you're in the control domain". This ultimately comes from the SIF flags provided at VM start. This patch exposes all SIF flags in /sys/hypervisor/start_flags/ as boolean files, one for each bit, returning '1' if set, '0' otherwise. Two known flags, 'privileged' and 'initdomain', are explicitly named, and all remaining flags can be accessed via generically named files, as suggested by Andrew Cooper. Signed-off-by: Per Bilse <[email protected]> Reviewed-by: Juergen Gross <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Juergen Gross <[email protected]>
1 parent ceaa837 commit 415dab3

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

Documentation/ABI/stable/sysfs-hypervisor-xen

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,16 @@ Contact: [email protected]
120120
Description: If running under Xen:
121121
The Xen version is in the format <major>.<minor><extra>
122122
This is the <minor> part of it.
123+
124+
What: /sys/hypervisor/start_flags/*
125+
Date: March 2023
126+
KernelVersion: 6.3.0
127+
128+
Description: If running under Xen:
129+
All bits in Xen's start-flags are represented as
130+
boolean files, returning '1' if set, '0' otherwise.
131+
This takes the place of the defunct /proc/xen/capabilities,
132+
which would contain "control_d" on dom0, and be empty
133+
otherwise. This flag is now exposed as "initdomain" in
134+
addition to the "privileged" flag; all other possible flags
135+
are accessible as "unknownXX".

drivers/xen/sys-hypervisor.c

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ struct hyp_sysfs_attr {
3131
struct attribute attr;
3232
ssize_t (*show)(struct hyp_sysfs_attr *, char *);
3333
ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
34-
void *hyp_attr_data;
34+
union {
35+
void *hyp_attr_data;
36+
unsigned long hyp_attr_value;
37+
};
3538
};
3639

3740
static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
@@ -399,6 +402,60 @@ static int __init xen_sysfs_properties_init(void)
399402
return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
400403
}
401404

405+
#define FLAG_UNAME "unknown"
406+
#define FLAG_UNAME_FMT FLAG_UNAME "%02u"
407+
#define FLAG_UNAME_MAX sizeof(FLAG_UNAME "XX")
408+
#define FLAG_COUNT (sizeof(xen_start_flags) * BITS_PER_BYTE)
409+
static_assert(sizeof(xen_start_flags) <=
410+
sizeof_field(struct hyp_sysfs_attr, hyp_attr_value));
411+
412+
static ssize_t flag_show(struct hyp_sysfs_attr *attr, char *buffer)
413+
{
414+
char *p = buffer;
415+
416+
*p++ = '0' + ((xen_start_flags & attr->hyp_attr_value) != 0);
417+
*p++ = '\n';
418+
return p - buffer;
419+
}
420+
421+
#define FLAG_NODE(flag, node) \
422+
[ilog2(flag)] = { \
423+
.attr = { .name = #node, .mode = 0444 },\
424+
.show = flag_show, \
425+
.hyp_attr_value = flag \
426+
}
427+
428+
/*
429+
* Add new, known flags here. No other changes are required, but
430+
* note that each known flag wastes one entry in flag_unames[].
431+
* The code/complexity machinations to avoid this isn't worth it
432+
* for a few entries, but keep it in mind.
433+
*/
434+
static struct hyp_sysfs_attr flag_attrs[FLAG_COUNT] = {
435+
FLAG_NODE(SIF_PRIVILEGED, privileged),
436+
FLAG_NODE(SIF_INITDOMAIN, initdomain)
437+
};
438+
static struct attribute_group xen_flags_group = {
439+
.name = "start_flags",
440+
.attrs = (struct attribute *[FLAG_COUNT + 1]){}
441+
};
442+
static char flag_unames[FLAG_COUNT][FLAG_UNAME_MAX];
443+
444+
static int __init xen_sysfs_flags_init(void)
445+
{
446+
for (unsigned fnum = 0; fnum != FLAG_COUNT; fnum++) {
447+
if (likely(flag_attrs[fnum].attr.name == NULL)) {
448+
sprintf(flag_unames[fnum], FLAG_UNAME_FMT, fnum);
449+
flag_attrs[fnum].attr.name = flag_unames[fnum];
450+
flag_attrs[fnum].attr.mode = 0444;
451+
flag_attrs[fnum].show = flag_show;
452+
flag_attrs[fnum].hyp_attr_value = 1 << fnum;
453+
}
454+
xen_flags_group.attrs[fnum] = &flag_attrs[fnum].attr;
455+
}
456+
return sysfs_create_group(hypervisor_kobj, &xen_flags_group);
457+
}
458+
402459
#ifdef CONFIG_XEN_HAVE_VPMU
403460
struct pmu_mode {
404461
const char *name;
@@ -539,18 +596,22 @@ static int __init hyper_sysfs_init(void)
539596
ret = xen_sysfs_properties_init();
540597
if (ret)
541598
goto prop_out;
599+
ret = xen_sysfs_flags_init();
600+
if (ret)
601+
goto flags_out;
542602
#ifdef CONFIG_XEN_HAVE_VPMU
543603
if (xen_initial_domain()) {
544604
ret = xen_sysfs_pmu_init();
545605
if (ret) {
546-
sysfs_remove_group(hypervisor_kobj,
547-
&xen_properties_group);
548-
goto prop_out;
606+
sysfs_remove_group(hypervisor_kobj, &xen_flags_group);
607+
goto flags_out;
549608
}
550609
}
551610
#endif
552611
goto out;
553612

613+
flags_out:
614+
sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
554615
prop_out:
555616
sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
556617
uuid_out:

0 commit comments

Comments
 (0)