kvm: arm64: Disclose SPCI partition details in sysfs
This allows user space to discover the preloaded partitions. Only
information that a VMM needs is made available.
Signed-off-by: Andrew Scull <ascull@google.com>
diff --git a/Documentation/ABI/testing/sysfs-hypervisor-spci b/Documentation/ABI/testing/sysfs-hypervisor-spci
new file mode 100644
index 0000000..48f0b55
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-hypervisor-spci
@@ -0,0 +1,18 @@
+What: /sys/hypervisor/spci/partitionX/uuid
+Date: April 2020
+KernelVersion: 5.8
+Contact: kvmarm@lists.cs.columbia.edu
+Description: The UUID of the partition.
+
+What: /sys/hypervisor/spci/partitionX/vcpus
+Date: April 2020
+KernelVersion: 5.8
+Contact: kvmarm@lists.cs.columbia.edu
+Description: The number of vCPUs declared by the partition.
+
+What: /sys/hypervisor/spci/partitionX/exec_state
+Date: April 2020
+KernelVersion: 5.8
+Contact: kvmarm@lists.cs.columbia.edu
+Description: The execution state of the partition.
+ Currently "AArch32" or "AArch64".
diff --git a/MAINTAINERS b/MAINTAINERS
index 7bff7e9..3130c32 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9295,6 +9295,7 @@
L: kvmarm@lists.cs.columbia.edu
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
+F: Documentation/ABI/testing/sysfs-hypervisor-spci
F: arch/arm64/include/asm/kvm*
F: arch/arm64/include/uapi/asm/kvm*
F: arch/arm64/kvm/
diff --git a/arch/arm64/kvm/spci.c b/arch/arm64/kvm/spci.c
index d73f956..b5225bd 100644
--- a/arch/arm64/kvm/spci.c
+++ b/arch/arm64/kvm/spci.c
@@ -157,6 +157,60 @@
return 0;
}
+static struct kobj_type spci_part_ktype = {
+ .sysfs_ops = &kobj_sysfs_ops,
+};
+
+#define kobj_to_part(kobj) container_of(kobj, struct kvm_spci_partition, kobj)
+#define SPCI_PART_ATTR_RO(_name, _fmt, ...) \
+static ssize_t _name##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+{ \
+ struct kvm_spci_partition *part = kobj_to_part(kobj); \
+ \
+ return sprintf(buf, _fmt, __VA_ARGS__); \
+} \
+static struct kobj_attribute spci_part_attr_##_name = __ATTR_RO(_name)
+
+SPCI_PART_ATTR_RO(uuid, "%pU\n", &part->uuid);
+SPCI_PART_ATTR_RO(vcpus, "%d\n", part->nr_vcpus);
+SPCI_PART_ATTR_RO(exec_state, "%s\n", part->is_32bit ? "AArch32" : "AArch64");
+
+static struct attribute *spci_part_attrs[] = {
+ &spci_part_attr_uuid.attr,
+ &spci_part_attr_vcpus.attr,
+ &spci_part_attr_exec_state.attr,
+ NULL,
+};
+
+static const struct attribute_group spci_part_attr_group = {
+ .attrs = spci_part_attrs,
+};
+
+static struct kobject *spci_kobj;
+
+static int spci_partition_create_sysfs(struct kvm_spci_partition *part)
+{
+ int err;
+
+ err = kobject_init_and_add(&part->kobj, &spci_part_ktype, spci_kobj,
+ "partition%d", part->id);
+ if (err)
+ goto out;
+
+ err = sysfs_create_group(&part->kobj, &spci_part_attr_group);
+ if (err)
+ goto out_put_kobj;
+
+ return 0;
+
+out_put_kobj:
+ kobject_put(&part->kobj);
+out:
+ return err;
+}
+
static int spci_parse_partitions(struct device_node *spci_np)
{
struct device_node *np, *prev_np = spci_np;
@@ -223,6 +277,10 @@
}
part->id = nr_parts;
+ if (spci_partition_create_sysfs(part)) {
+ kvm_err("%s: failed to create sysfs entries\n", pfx);
+ goto next_free_part;
+ }
++nr_parts;
INIT_LIST_HEAD(&part->list);
@@ -307,8 +365,13 @@
int kvm_spci_init(void)
{
- int ret = spci_parse_dt_node();
+ int ret;
+ spci_kobj = kobject_create_and_add("spci", hypervisor_kobj);
+ if (!spci_kobj)
+ return -ENOMEM;
+
+ ret = spci_parse_dt_node();
if (ret)
return ret;
diff --git a/include/kvm/arm_spci.h b/include/kvm/arm_spci.h
index 54fd69b..71fde30 100644
--- a/include/kvm/arm_spci.h
+++ b/include/kvm/arm_spci.h
@@ -8,6 +8,7 @@
#define __KVM_ARM_SPCI_H
#include <linux/of_reserved_mem.h>
+#include <linux/kobject.h>
enum kvm_spci_mem_prot {
KVM_SPCI_MEM_PROT_X = 1 << 0,
@@ -23,6 +24,7 @@
};
struct kvm_spci_partition {
+ struct kobject kobj;
struct list_head list;
int id;
uuid_t uuid;