From patchwork Wed Apr 3 01:57:48 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Wood X-Patchwork-Id: 2383561 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id D3C7A3FE81 for ; Wed, 3 Apr 2013 01:59:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760836Ab3DCB75 (ORCPT ); Tue, 2 Apr 2013 21:59:57 -0400 Received: from [216.32.180.16] ([216.32.180.16]:20514 "EHLO va3outboundpool.messaging.microsoft.com" rhost-flags-FAIL-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1759239Ab3DCB7z (ORCPT ); Tue, 2 Apr 2013 21:59:55 -0400 Received: from mail136-va3-R.bigfish.com (10.7.14.246) by VA3EHSOBE012.bigfish.com (10.7.40.62) with Microsoft SMTP Server id 14.1.225.23; Wed, 3 Apr 2013 01:58:04 +0000 Received: from mail136-va3 (localhost [127.0.0.1]) by mail136-va3-R.bigfish.com (Postfix) with ESMTP id 1F3AD4A02D2; Wed, 3 Apr 2013 01:58:04 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 1 X-BigFish: VS1(z551bizzz1f42h1fc6h1ee6h1de0h1202h1e76h1d1ah1d2ahzz8275bhz2dh2a8h668h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1155h) Received: from mail136-va3 (localhost.localdomain [127.0.0.1]) by mail136-va3 (MessageSwitch) id 1364954281838578_17108; Wed, 3 Apr 2013 01:58:01 +0000 (UTC) Received: from VA3EHSMHS032.bigfish.com (unknown [10.7.14.230]) by mail136-va3.bigfish.com (Postfix) with ESMTP id C42DC3A0081; Wed, 3 Apr 2013 01:58:01 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS032.bigfish.com (10.7.99.42) with Microsoft SMTP Server (TLS) id 14.1.225.23; Wed, 3 Apr 2013 01:57:56 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-005.039d.mgd.msft.net (10.84.1.17) with Microsoft SMTP Server (TLS) id 14.2.328.11; Wed, 3 Apr 2013 01:57:55 +0000 Received: from snotra.am.freescale.net ([10.214.81.96]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id r331vrtk019716; Tue, 2 Apr 2013 18:57:55 -0700 From: Scott Wood To: Alexander Graf CC: , , , Scott Wood Subject: [RFC PATCH v3 1/6] kvm: add device control API Date: Tue, 2 Apr 2013 20:57:48 -0500 Message-ID: <1364954273-18196-2-git-send-email-scottwood@freescale.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1364954273-18196-1-git-send-email-scottwood@freescale.com> References: <1364856473-25245-1-git-send-email-scottwood@freescale.com> <1364954273-18196-1-git-send-email-scottwood@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Currently, devices that are emulated inside KVM are configured in a hardcoded manner based on an assumption that any given architecture only has one way to do it. If there's any need to access device state, it is done through inflexible one-purpose-only IOCTLs (e.g. KVM_GET/SET_LAPIC). Defining new IOCTLs for every little thing is cumbersome and depletes a limited numberspace. This API provides a mechanism to instantiate a device of a certain type, returning an ID that can be used to set/get attributes of the device. Attributes may include configuration parameters (e.g. register base address), device state, operational commands, etc. It is similar to the ONE_REG API, except that it acts on devices rather than vcpus. Both device types and individual attributes can be tested without having to create the device or get/set the attribute, without the need for separately managing enumerated capabilities. Signed-off-by: Scott Wood --- v3: remove some changes that were merged into this patch by accident, and fix the error documentation for KVM_CREATE_DEVICE. NOTE: I had some difficulty figuring out what ioctl numbers I should assign... it seems that at one point care was taken to keep vcpu and vm ioctls separate, but some overlap exists now (despite not exhausing the ioctl space). Some of that was my fault, but not all of it. :-) I moved to a new ioctl range for device control -- please let me know if there's something else you'd prefer I do. --- Documentation/virtual/kvm/api.txt | 70 ++++++++++++++++++++++++++++++ Documentation/virtual/kvm/devices/README | 1 + include/uapi/linux/kvm.h | 27 ++++++++++++ virt/kvm/kvm_main.c | 31 +++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 Documentation/virtual/kvm/devices/README diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 976eb65..d52f3f9 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2173,6 +2173,76 @@ header; first `n_valid' valid entries with contents from the data written, then `n_invalid' invalid entries, invalidating any previously valid entries found. +4.79 KVM_CREATE_DEVICE + +Capability: KVM_CAP_DEVICE_CTRL +Type: vm ioctl +Parameters: struct kvm_create_device (in/out) +Returns: 0 on success, -1 on error +Errors: + ENODEV: The device type is unknown or unsupported + EEXIST: Device already created, and this type of device may not + be instantiated multiple times + + Other error conditions may be defined by individual device types or + have their standard meanings. + +Creates an emulated device in the kernel. The file descriptor returned +in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR. + +If the KVM_CREATE_DEVICE_TEST flag is set, only test whether the +device type is supported (not necessarily whether it can be created +in the current vm). + +Individual devices should not define flags. Attributes should be used +for specifying any behavior that is not implied by the device type +number. + +struct kvm_create_device { + __u32 type; /* in: KVM_DEV_TYPE_xxx */ + __u32 fd; /* out: device handle */ + __u32 flags; /* in: KVM_CREATE_DEVICE_xxx */ +}; + +4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR + +Capability: KVM_CAP_DEVICE_CTRL +Type: device ioctl +Parameters: struct kvm_device_attr +Returns: 0 on success, -1 on error +Errors: + ENXIO: The group or attribute is unknown/unsupported for this device + EPERM: The attribute cannot (currently) be accessed this way + (e.g. read-only attribute, or attribute that only makes + sense when the device is in a different state) + + Other error conditions may be defined by individual device types. + +Gets/sets a specified piece of device configuration and/or state. The +semantics are device-specific. See individual device documentation in +the "devices" directory. As with ONE_REG, the size of the data +transferred is defined by the particular attribute. + +struct kvm_device_attr { + __u32 flags; /* no flags currently defined */ + __u32 group; /* device-defined */ + __u64 attr; /* group-defined */ + __u64 addr; /* userspace address of attr data */ +}; + +4.81 KVM_HAS_DEVICE_ATTR + +Capability: KVM_CAP_DEVICE_CTRL +Type: device ioctl +Parameters: struct kvm_device_attr +Returns: 0 on success, -1 on error +Errors: + ENXIO: The group or attribute is unknown/unsupported for this device + +Tests whether a device supports a particular attribute. A successful +return indicates the attribute is implemented. It does not necessarily +indicate that the attribute can be read or written in the device's +current state. "addr" is ignored. 4.77 KVM_ARM_VCPU_INIT diff --git a/Documentation/virtual/kvm/devices/README b/Documentation/virtual/kvm/devices/README new file mode 100644 index 0000000..34a6983 --- /dev/null +++ b/Documentation/virtual/kvm/devices/README @@ -0,0 +1 @@ +This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL. diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 74d0ff3..20ce2d2 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -668,6 +668,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_PPC_EPR 86 #define KVM_CAP_ARM_PSCI 87 #define KVM_CAP_ARM_SET_DEVICE_ADDR 88 +#define KVM_CAP_DEVICE_CTRL 89 #ifdef KVM_CAP_IRQ_ROUTING @@ -909,6 +910,32 @@ struct kvm_s390_ucas_mapping { #define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr) /* + * Device control API, available with KVM_CAP_DEVICE_CTRL + */ +#define KVM_CREATE_DEVICE_TEST 1 + +struct kvm_create_device { + __u32 type; /* in: KVM_DEV_TYPE_xxx */ + __u32 fd; /* out: device handle */ + __u32 flags; /* in: KVM_CREATE_DEVICE_xxx */ +}; + +struct kvm_device_attr { + __u32 flags; /* no flags currently defined */ + __u32 group; /* device-defined */ + __u64 attr; /* group-defined */ + __u64 addr; /* userspace address of attr data */ +}; + +/* ioctl for vm fd */ +#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device) + +/* ioctls for fds returned by KVM_CREATE_DEVICE */ +#define KVM_SET_DEVICE_ATTR _IOW(KVMIO, 0xe1, struct kvm_device_attr) +#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr) +#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr) + +/* * ioctls for vcpu fds */ #define KVM_RUN _IO(KVMIO, 0x80) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index ff71541..ed033c0 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2158,6 +2158,17 @@ out: } #endif +static int kvm_ioctl_create_device(struct kvm *kvm, + struct kvm_create_device *cd) +{ + bool test = cd->flags & KVM_CREATE_DEVICE_TEST; + + switch (cd->type) { + default: + return -ENODEV; + } +} + static long kvm_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -2272,6 +2283,26 @@ static long kvm_vm_ioctl(struct file *filp, break; } #endif + case KVM_CREATE_DEVICE: { + struct kvm_create_device cd; + + r = -EFAULT; + if (copy_from_user(&cd, argp, sizeof(cd))) + goto out; + + mutex_lock(&kvm->lock); + r = kvm_ioctl_create_device(kvm, &cd); + mutex_unlock(&kvm->lock); + if (r) + goto out; + + r = -EFAULT; + if (copy_to_user(argp, &cd, sizeof(cd))) + goto out; + + r = 0; + break; + } default: r = kvm_arch_vm_ioctl(filp, ioctl, arg); if (r == -ENOTTY)