From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoffer Dall Subject: =?UTF-8?q?=5BRFC=20PATCH=202/3=5D=20KVM=3A=20ARM=3A=20Introduce=20KVM=5FSET=5FDEVICE=5FADDRESS=20ioctl?= Date: Sat, 13 Oct 2012 20:04:24 -0400 Message-ID: <1350173065-35350-3-git-send-email-c.dall@virtualopensystems.com> References: <1350173065-35350-1-git-send-email-c.dall@virtualopensystems.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: peter.maydell@linaro.org, marc.zyngier@arm.com, Christoffer Dall To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Return-path: Received: from mail-qa0-f46.google.com ([209.85.216.46]:45943 "EHLO mail-qa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753086Ab2JNAEu (ORCPT ); Sat, 13 Oct 2012 20:04:50 -0400 Received: by mail-qa0-f46.google.com with SMTP id c26so452957qad.19 for ; Sat, 13 Oct 2012 17:04:49 -0700 (PDT) In-Reply-To: <1350173065-35350-1-git-send-email-c.dall@virtualopensystems.com> Sender: kvm-owner@vger.kernel.org List-ID: On ARM (and possibly other architectures) some bits are specific to the model being emulated for the guest and user space needs a way to tell the kernel about those bits. An example is mmio device base addresses, where KVM must know the base address for a given device to properly emulate mmio accesses within a certain address range or directly map a device with virtualiation extensions into the guest address space. We try to make this API slightly more generic than for our specific use= , but so far only the VGIC uses this feature. Signed-off-by: Christoffer Dall --- Documentation/virtual/kvm/api.txt | 30 +++++++++++++++++++++++++++++= + arch/arm/include/asm/kvm.h | 13 +++++++++++++ arch/arm/include/asm/kvm_mmu.h | 1 + arch/arm/include/asm/kvm_vgic.h | 6 ++++++ arch/arm/kvm/arm.c | 31 +++++++++++++++++++++++++++++= +- arch/arm/kvm/vgic.c | 34 +++++++++++++++++++++++++++++= ++--- include/linux/kvm.h | 8 ++++++++ 7 files changed, 119 insertions(+), 4 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/= kvm/api.txt index 26e953d..30ddcac 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2118,6 +2118,36 @@ for the emulated platofrm (see KVM_SET_DEVICE_AD= DRESS), but before the CPU is initally run. =20 =20 +4.80 KVM_SET_DEVICE_ADDRESS + +Capability: KVM_CAP_SET_DEVICE_ADDRESS +Architectures: arm +Type: vm ioctl +Parameters: struct kvm_device_address (in) +Returns: 0 on success, -1 on error +Errors: + ENODEV: The device id is unknwown + ENXIO: Device not supported in configuration + E2BIG: Address outside of guest physical address space + +struct kvm_device_address { + __u32 id; + __u64 addr; +}; + +Specify a device address in the guest's physical address space where g= uests +can access emulated or directly exposed devices, which the host kernel= needs +to know about. The id field is an architecture specific identifier for= a +specific device. + +ARM divides the id field into two parts, a device ID and an address ty= pe id +specific to the individual device. + + =C2=A0bits: | 31 ... 16 | 15 ... 0 | + field: | device id | addr type id | + + + 5. The kvm_run structure ------------------------ =20 diff --git a/arch/arm/include/asm/kvm.h b/arch/arm/include/asm/kvm.h index b6eaf0c..dfd60cc 100644 --- a/arch/arm/include/asm/kvm.h +++ b/arch/arm/include/asm/kvm.h @@ -42,6 +42,19 @@ struct kvm_regs { #define KVM_ARM_TARGET_CORTEX_A15 0 #define KVM_ARM_NUM_TARGETS 1 =20 +/* KVM_SET_DEVICE_ADDRESS ioctl id encoding */ +#define KVM_DEVICE_TYPE_SHIFT 0 +#define KVM_DEVICE_TYPE_MASK (0xffff << KVM_DEVICE_TYPE_SHIFT) +#define KVM_DEVICE_ID_SHIFT 16 +#define KVM_DEVICE_ID_MASK (0xffff << KVM_DEVICE_ID_SHIFT) + +/* Supported device IDs */ +#define KVM_ARM_DEVICE_VGIC_V2 0 + +/* Supported VGIC address types */ +#define KVM_VGIC_V2_ADDR_TYPE_DIST 0 +#define KVM_VGIC_V2_ADDR_TYPE_CPU 1 + struct kvm_vcpu_init { __u32 target; __u32 features[7]; diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_= mmu.h index ecfaaf0..0aef24f 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -26,6 +26,7 @@ * To save a bit of memory and to avoid alignment issues we assume 39-= bit IPA * for now, but remember that the level-1 table must be aligned to its= size. */ +#define KVM_MAX_IPA ((1ULL << 38) - 1) #define PTRS_PER_PGD2 512 #define PGD2_ORDER get_order(PTRS_PER_PGD2 * sizeof(pgd_t)) =20 diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm= _vgic.h index 588c637..a688132 100644 --- a/arch/arm/include/asm/kvm_vgic.h +++ b/arch/arm/include/asm/kvm_vgic.h @@ -242,6 +242,7 @@ struct kvm_exit_mmio; =20 #ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_hyp_init(void); +int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr); int kvm_vgic_init(struct kvm *kvm); void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu); void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu); @@ -261,6 +262,11 @@ static inline int kvm_vgic_hyp_init(void) return 0; } =20 +static inline int kvm_vgic_set_addr(struct kvm *kvm, unsigned long typ= e, u64 addr) +{ + return 0; +} + static inline int kvm_vgic_init(struct kvm *kvm) { return 0; diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 85c76e4..67c8cc2 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -207,6 +207,9 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_COALESCED_MMIO: r =3D KVM_COALESCED_MMIO_PAGE_OFFSET; break; + case KVM_CAP_SET_DEVICE_ADDR: + r =3D 1; + break; default: r =3D 0; break; @@ -859,20 +862,46 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, s= truct kvm_dirty_log *log) return -EINVAL; } =20 +static int kvm_vm_ioctl_set_device_address(struct kvm *kvm, + struct kvm_device_address *dev_addr) +{ + unsigned long dev_id, type; + + dev_id =3D (dev_addr->id & KVM_DEVICE_ID_MASK) >> KVM_DEVICE_ID_SHIFT= ; + type =3D (dev_addr->id & KVM_DEVICE_TYPE_MASK) >> KVM_DEVICE_TYPE_SHI= =46T; + + switch (dev_id) { + case KVM_ARM_DEVICE_VGIC_V2: + if (!vgic_present) + return -ENXIO; + return kvm_vgic_set_addr(kvm, type, dev_addr->addr); + default: + return -ENODEV; + } +} + long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { + struct kvm *kvm =3D filp->private_data; + void __user *argp =3D (void __user *)arg; =20 switch (ioctl) { #ifdef CONFIG_KVM_ARM_VGIC case KVM_CREATE_IRQCHIP: { - struct kvm *kvm =3D filp->private_data; if (vgic_present) return kvm_vgic_init(kvm); else return -EINVAL; } #endif + case KVM_SET_DEVICE_ADDRESS: { + struct kvm_device_address dev_addr; + + if (copy_from_user(&dev_addr, argp, sizeof(dev_addr))) + return -EFAULT; + return kvm_vm_ioctl_set_device_address(kvm, &dev_addr); + } default: return -EINVAL; } diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index 494d94d..1e4be2d 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c @@ -65,12 +65,17 @@ * interrupt line to be sampled again. */ =20 -/* Temporary hacks, need to be provided by userspace emulation */ -#define VGIC_DIST_BASE 0x2c001000 +#define VGIC_ADDR_UNDEF (-1) #define VGIC_DIST_SIZE 0x1000 -#define VGIC_CPU_BASE 0x2c002000 #define VGIC_CPU_SIZE 0x2000 =20 +/* Physical address of vgic virtual cpu interface */ +static phys_addr_t vgic_vcpu_base; + +/* Guest physical addresses used by the guest to access the vgic */ +static unsigned long vgic_guest_dist_base =3D VGIC_ADDR_UNDEF; +static unsigned long vgic_guest_cpu_base =3D VGIC_ADDR_UNDEF; + /* Virtual control interface base address */ static void __iomem *vgic_vctrl_base; =20 @@ -1117,3 +1122,26 @@ out: =20 return ret; } + +int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr) +{ + int r =3D 0; + + if (addr > KVM_MAX_IPA) + return -E2BIG; + + mutex_lock(&kvm->lock); + switch (type) { + case KVM_VGIC_V2_ADDR_TYPE_DIST: + vgic_guest_dist_base =3D addr; + break; + case KVM_VGIC_V2_ADDR_TYPE_CPU: + vgic_guest_cpu_base =3D addr; + break; + default: + r =3D -ENODEV; + } + + mutex_unlock(&kvm->lock); + return r; +} diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 90ee023..e9da8ec 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -627,6 +627,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_READONLY_MEM 81 #endif #define KVM_CAP_INIT_IRQCHIP 82 +#define KVM_CAP_SET_DEVICE_ADDR 83 =20 #ifdef KVM_CAP_IRQ_ROUTING =20 @@ -760,6 +761,11 @@ struct kvm_msi { __u8 pad[16]; }; =20 +struct kvm_device_address { + __u32 id; + __u64 addr; +}; + /* * ioctls for VM fds */ @@ -842,6 +848,8 @@ struct kvm_s390_ucas_mapping { #define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32) /* Available with KVM_CAP_INIT_IRQCHIP */ #define KVM_INIT_IRQCHIP _IO(KVMIO, 0xa8) +/* Available with KVM_CAP_SET_DEVICE_ADDR */ +#define KVM_SET_DEVICE_ADDRESS _IOW(KVMIO, 0xa9, struct kvm_device_= address) =20 /* * ioctls for vcpu fds --=20 1.7.9.5