]> Git Repo - linux.git/commitdiff
KVM: s390: pv: Add query interface
authorJanosch Frank <[email protected]>
Tue, 17 May 2022 16:36:21 +0000 (16:36 +0000)
committerChristian Borntraeger <[email protected]>
Wed, 1 Jun 2022 14:57:14 +0000 (16:57 +0200)
Some of the query information is already available via sysfs but
having a IOCTL makes the information easier to retrieve.

Signed-off-by: Janosch Frank <[email protected]>
Reviewed-by: Claudio Imbrenda <[email protected]>
Reviewed-by: Steffen Eiden <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Message-Id: <20220517163629[email protected]>
Signed-off-by: Christian Borntraeger <[email protected]>
arch/s390/kvm/kvm-s390.c
include/uapi/linux/kvm.h

index 76ad6408cb2cd0c2a4f5e91cbc3f735a7721e416..5859f243d2870914e883b21a3f2c4904ccdacf9c 100644 (file)
@@ -2224,6 +2224,42 @@ static int kvm_s390_cpus_to_pv(struct kvm *kvm, u16 *rc, u16 *rrc)
        return r;
 }
 
+/*
+ * Here we provide user space with a direct interface to query UV
+ * related data like UV maxima and available features as well as
+ * feature specific data.
+ *
+ * To facilitate future extension of the data structures we'll try to
+ * write data up to the maximum requested length.
+ */
+static ssize_t kvm_s390_handle_pv_info(struct kvm_s390_pv_info *info)
+{
+       ssize_t len_min;
+
+       switch (info->header.id) {
+       case KVM_PV_INFO_VM: {
+               len_min =  sizeof(info->header) + sizeof(info->vm);
+
+               if (info->header.len_max < len_min)
+                       return -EINVAL;
+
+               memcpy(info->vm.inst_calls_list,
+                      uv_info.inst_calls_list,
+                      sizeof(uv_info.inst_calls_list));
+
+               /* It's max cpuid not max cpus, so it's off by one */
+               info->vm.max_cpus = uv_info.max_guest_cpu_id + 1;
+               info->vm.max_guests = uv_info.max_num_sec_conf;
+               info->vm.max_guest_addr = uv_info.max_sec_stor_addr;
+               info->vm.feature_indication = uv_info.uv_feature_indications;
+
+               return len_min;
+       }
+       default:
+               return -EINVAL;
+       }
+}
+
 static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
 {
        int r = 0;
@@ -2360,6 +2396,46 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
                             cmd->rc, cmd->rrc);
                break;
        }
+       case KVM_PV_INFO: {
+               struct kvm_s390_pv_info info = {};
+               ssize_t data_len;
+
+               /*
+                * No need to check the VM protection here.
+                *
+                * Maybe user space wants to query some of the data
+                * when the VM is still unprotected. If we see the
+                * need to fence a new data command we can still
+                * return an error in the info handler.
+                */
+
+               r = -EFAULT;
+               if (copy_from_user(&info, argp, sizeof(info.header)))
+                       break;
+
+               r = -EINVAL;
+               if (info.header.len_max < sizeof(info.header))
+                       break;
+
+               data_len = kvm_s390_handle_pv_info(&info);
+               if (data_len < 0) {
+                       r = data_len;
+                       break;
+               }
+               /*
+                * If a data command struct is extended (multiple
+                * times) this can be used to determine how much of it
+                * is valid.
+                */
+               info.header.len_written = data_len;
+
+               r = -EFAULT;
+               if (copy_to_user(argp, &info, data_len))
+                       break;
+
+               r = 0;
+               break;
+       }
        default:
                r = -ENOTTY;
        }
index 5088bd9f1922851fb62ea7562ccbeb6b64eeed02..5a5f66026dd3ebdbb326384685a9ac4431361006 100644 (file)
@@ -1660,6 +1660,30 @@ struct kvm_s390_pv_unp {
        __u64 tweak;
 };
 
+enum pv_cmd_info_id {
+       KVM_PV_INFO_VM,
+};
+
+struct kvm_s390_pv_info_vm {
+       __u64 inst_calls_list[4];
+       __u64 max_cpus;
+       __u64 max_guests;
+       __u64 max_guest_addr;
+       __u64 feature_indication;
+};
+
+struct kvm_s390_pv_info_header {
+       __u32 id;
+       __u32 len_max;
+       __u32 len_written;
+       __u32 reserved;
+};
+
+struct kvm_s390_pv_info {
+       struct kvm_s390_pv_info_header header;
+       struct kvm_s390_pv_info_vm vm;
+};
+
 enum pv_cmd_id {
        KVM_PV_ENABLE,
        KVM_PV_DISABLE,
@@ -1668,6 +1692,7 @@ enum pv_cmd_id {
        KVM_PV_VERIFY,
        KVM_PV_PREP_RESET,
        KVM_PV_UNSHARE_ALL,
+       KVM_PV_INFO,
 };
 
 struct kvm_pv_cmd {
This page took 0.076402 seconds and 4 git commands to generate.