From: Ekaterina Tumanova <tuman...@linux.vnet.ibm.com>

Add KVM_DEV_TYPE_S390_CONFIG kvm device that contains
configuration and control attributes of particular vm.
The device is created by KVM_CREATE_DEVICE ioctl.
The attributes may be retrieved and stored by calling
KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls.

Signed-off-by: Ekaterina Tumanova <tuman...@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntrae...@de.ibm.com>
---
 Documentation/virtual/kvm/devices/s390_config.txt |  13 +++
 arch/s390/include/asm/kvm_host.h                  |   6 +
 arch/s390/include/uapi/asm/kvm.h                  |  11 ++
 arch/s390/kvm/Makefile                            |   2 +-
 arch/s390/kvm/config.c                            | 133 ++++++++++++++++++++++
 arch/s390/kvm/kvm-s390.c                          |   7 ++
 arch/s390/kvm/kvm-s390.h                          |   4 +
 arch/s390/kvm/priv.c                              |   6 +-
 include/linux/kvm_host.h                          |   1 +
 include/uapi/linux/kvm.h                          |   1 +
 virt/kvm/kvm_main.c                               |   3 +
 11 files changed, 185 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/virtual/kvm/devices/s390_config.txt
 create mode 100644 arch/s390/kvm/config.c

diff --git a/Documentation/virtual/kvm/devices/s390_config.txt 
b/Documentation/virtual/kvm/devices/s390_config.txt
new file mode 100644
index 0000000..f9bc251
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/s390_config.txt
@@ -0,0 +1,13 @@
+S390 Config Device
+==================
+
+The s390 config device is used for storage and retrieval of various kinds
+of configuration related information which should be shared between kvm
+and userspace.
+
+Groups:
+KVM_DEV_CONFIG_GROUP
+
+Attributes for KVM_DEV_CONFIG_GROUP:
+KVM_DEV_CONFIG_NAME - The name for this vm instance. A string of at
+                          most 128 characters.
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 154b600..da93b6e 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -277,6 +277,11 @@ struct s390_io_adapter {
 #define MAX_S390_IO_ADAPTERS ((MAX_ISC + 1) * 8)
 #define MAX_S390_ADAPTER_MAPS 256
 
+struct kvm_s390_config {
+       struct mutex lock;
+       struct kvm_s390_attr_name name;
+};
+
 struct kvm_arch{
        struct sca_block *sca;
        debug_info_t *dbf;
@@ -286,6 +291,7 @@ struct kvm_arch{
        int css_support;
        int use_irqchip;
        struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
+       struct kvm_s390_config *cfg;
 };
 
 #define KVM_HVA_ERR_BAD                (-1UL)
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index c003c6a..d53dd45 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -79,6 +79,17 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
+
+
+/* config device specific GROUPS */
+
+#define KVM_DEV_CONFIG_GROUP           0
+#define KVM_DEV_CONFIG_NAME            0
+
+struct kvm_s390_attr_name {
+       char name[128];
+};
+
 #define KVM_SYNC_PREFIX (1UL << 0)
 #define KVM_SYNC_GPRS   (1UL << 1)
 #define KVM_SYNC_ACRS   (1UL << 2)
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index d3adb37..79f130b 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -11,5 +11,5 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o  
$(KVM)/async_pf.o $(KVM)/irqch
 
 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
-kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o 
diag.o
+kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o 
diag.o config.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/kvm/config.c b/arch/s390/kvm/config.c
new file mode 100644
index 0000000..f887116
--- /dev/null
+++ b/arch/s390/kvm/config.c
@@ -0,0 +1,133 @@
+/*
+ * handling CONFIG kvm device
+ *
+ * Copyright IBM Corp. 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Ekaterina Tumanova <tuman...@linux.vnet.ibm.com>
+ *               Christian Borntraeger <borntrae...@de.ibm.com>
+ */
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <asm/uaccess.h>
+#include "kvm-s390.h"
+
+static const struct kvm_s390_config config_defaults = {
+       .name = { "KVMguest" },
+};
+
+/*
+ * This is called from architecture code, since we access config even if
+ * userspace does not create a config device.
+ */
+struct kvm_s390_config *kvm_s390_config_init(void)
+{
+       struct kvm_s390_config *config;
+
+       config = kmalloc(sizeof(struct kvm_s390_config), GFP_KERNEL);
+       if (config) {
+               memcpy(config, &config_defaults, sizeof(*config));
+               mutex_init(&config->lock);
+       }
+
+       return config;
+}
+
+void kvm_s390_config_free(struct kvm_s390_config *config)
+{
+       kfree(config);
+}
+
+/*
+ * kvm accesses the config datastructure even if userspace did not create a
+ * config kvm device. So we only do kvm device related cleanups in the
+ * create and destroy callbacks.
+ */
+static int config_create(struct kvm_device *dev, u32 attr)
+{
+       return 0;
+}
+
+static void config_destroy(struct kvm_device *dev)
+{
+       kfree(dev);
+}
+
+static int config_set(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+       struct kvm_s390_config *config = dev->kvm->arch.cfg;
+       int ret;
+
+       switch (attr->attr) {
+       case KVM_DEV_CONFIG_NAME:
+               mutex_lock(&config->lock);
+               ret = copy_from_user(&config->name, (void __user *) attr->addr,
+                                    sizeof(config->name));
+               mutex_unlock(&config->lock);
+               return ret;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int config_get(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+       struct kvm_s390_config *config = dev->kvm->arch.cfg;
+       int ret;
+
+       switch (attr->attr) {
+       case KVM_DEV_CONFIG_NAME:
+               mutex_lock(&config->lock);
+               ret = copy_to_user((void __user *) attr->addr, &config->name,
+                                  sizeof(config->name));
+               mutex_unlock(&config->lock);
+               return ret;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int config_set_attr(struct kvm_device *dev, struct kvm_device_attr 
*attr)
+{
+       switch (attr->group) {
+       case KVM_DEV_CONFIG_GROUP:
+               return config_set(dev, attr);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int config_get_attr(struct kvm_device *dev, struct kvm_device_attr 
*attr)
+{
+       switch (attr->group) {
+       case KVM_DEV_CONFIG_GROUP:
+               return config_get(dev, attr);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int config_has_attr(struct kvm_device *dev, struct kvm_device_attr 
*attr)
+{
+       switch (attr->group) {
+       case KVM_DEV_CONFIG_GROUP:
+               switch (attr->attr) {
+               case KVM_DEV_CONFIG_NAME:
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+struct kvm_device_ops kvm_s390_config_ops = {
+       .name = "kvm_s390_config",
+       .create = config_create,
+       .destroy = config_destroy,
+       .get_attr = config_get_attr,
+       .set_attr = config_set_attr,
+       .has_attr = config_has_attr,
+};
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index b3ecb8f..4504015 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -307,8 +307,14 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
        kvm->arch.css_support = 0;
        kvm->arch.use_irqchip = 0;
+       kvm->arch.cfg = kvm_s390_config_init();
+       if (!kvm->arch.cfg)
+               goto out_gmap;
 
        return 0;
+out_gmap:
+       if (!kvm_is_ucontrol(kvm))
+               gmap_free(kvm->arch.gmap);
 out_nogmap:
        debug_unregister(kvm->arch.dbf);
 out_nodbf:
@@ -371,6 +377,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        if (!kvm_is_ucontrol(kvm))
                gmap_free(kvm->arch.gmap);
        kvm_s390_destroy_adapters(kvm);
+       kvm_s390_config_free(kvm->arch.cfg);
 }
 
 /* Section: vcpu related */
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 3c1e227..50185a3 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -168,4 +168,8 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
 int psw_extint_disabled(struct kvm_vcpu *vcpu);
 void kvm_s390_destroy_adapters(struct kvm *kvm);
 
+/* implemented in config.c */
+struct kvm_s390_config *kvm_s390_config_init(void);
+void kvm_s390_config_free(struct kvm_s390_config *config);
+
 #endif
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 476e9e2..4e5fba5 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/kvm.h>
+#include <linux/kvm_host.h>
 #include <linux/gfp.h>
 #include <linux/errno.h>
 #include <linux/compat.h>
@@ -414,7 +415,10 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, 
struct sysinfo_3_2_2 *mem)
        mem->vm[0].cpus_standby = 0;
        mem->vm[0].cpus_reserved = 0;
        mem->vm[0].caf = 1000;
-       memcpy(mem->vm[0].name, "KVMguest", 8);
+
+       mutex_lock(&vcpu->kvm->arch.cfg->lock);
+       memcpy(mem->vm[0].name, &vcpu->kvm->arch.cfg->name, 8);
+       mutex_unlock(&vcpu->kvm->arch.cfg->lock);
        ASCEBC(mem->vm[0].name, 8);
        memcpy(mem->vm[0].cpi, "KVM/Linux       ", 16);
        ASCEBC(mem->vm[0].cpi, 16);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 7d21cf9..5c5c39c 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1080,6 +1080,7 @@ extern struct kvm_device_ops kvm_xics_ops;
 extern struct kvm_device_ops kvm_vfio_ops;
 extern struct kvm_device_ops kvm_arm_vgic_v2_ops;
 extern struct kvm_device_ops kvm_flic_ops;
+extern struct kvm_device_ops kvm_s390_config_ops;
 
 #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
 
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index a8f4ee5..d0e738f 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -934,6 +934,7 @@ struct kvm_device_attr {
 #define   KVM_DEV_VFIO_GROUP_DEL                       2
 #define KVM_DEV_TYPE_ARM_VGIC_V2       5
 #define KVM_DEV_TYPE_FLIC              6
+#define KVM_DEV_TYPE_S390_CONFIG       7
 
 /*
  * ioctls for VM fds
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5fd4cf8..a9f909a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2285,6 +2285,9 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
        case KVM_DEV_TYPE_FLIC:
                ops = &kvm_flic_ops;
                break;
+       case KVM_DEV_TYPE_S390_CONFIG:
+               ops = &kvm_s390_config_ops;
+               break;
 #endif
        default:
                return -ENODEV;
-- 
1.8.4.2


Reply via email to