From patchwork Sat Nov 10 15:44:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 1724021 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 47ACE3FC8F for ; Sat, 10 Nov 2012 15:44:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752122Ab2KJPok (ORCPT ); Sat, 10 Nov 2012 10:44:40 -0500 Received: from mail-we0-f174.google.com ([74.125.82.174]:62582 "EHLO mail-we0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752109Ab2KJPoj (ORCPT ); Sat, 10 Nov 2012 10:44:39 -0500 Received: by mail-we0-f174.google.com with SMTP id t9so2184493wey.19 for ; Sat, 10 Nov 2012 07:44:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=subject:to:from:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=hOBHRoPhhwHOHKa9U8XVEIh1pgZmxGy5H1+NkBW+XDs=; b=SI/AY6p04iO+Epna9plkMW9O0qhZPdIOXCYNmnVJbXFaGMsf5Cv7Kv2TwJCpAHizjw G6ZpeccyMz1cjrqs1H9WdeMaNDWCO/Ko/xqm05HBCa3G+JYQRPZJsZQEXv4c5XfcSfY+ oJipG6ea8AZhTmQ628JZuXUvCO0uGGPsYggY5Rok0IgVmhJPhBdVAWvVNIzODENLmpoQ ETjOUIDKZOH/qO9jzy0y+3fqJL7UsRYNrTi434e6Z76bceSi7PVsREWdZ6wYHigUpRC6 pf8+cZoGV3zjcFGZNmgvrq0fSBJKaw8cibVq6QtBrAxLIUpPFq0e3H6jy1Ci3z7Iu840 eFRg== Received: by 10.180.93.234 with SMTP id cx10mr6980460wib.5.1352562278884; Sat, 10 Nov 2012 07:44:38 -0800 (PST) Received: from [127.0.1.1] (ip1.c116.obr91.cust.comxnet.dk. [87.72.8.103]) by mx.google.com with ESMTPS id f1sm6735212wiy.2.2012.11.10.07.44.37 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 10 Nov 2012 07:44:38 -0800 (PST) Subject: [PATCH v4 03/13] ARM: KVM: Initial VGIC infrastructure support To: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu From: Christoffer Dall Cc: Marc Zyngier Date: Sat, 10 Nov 2012 16:44:37 +0100 Message-ID: <20121110154437.3061.76180.stgit@chazy-air> In-Reply-To: <20121110154358.3061.16338.stgit@chazy-air> References: <20121110154358.3061.16338.stgit@chazy-air> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQm+AfBWuFvbc6PeS6sKgWZqEP3+RkSghBbEH16owz+YAp2ZKKb0LFddvdelDGnv9ehuTjDH Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Marc Zyngier Wire the basic framework code for VGIC support. Nothing to enable yet. Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/include/asm/kvm_host.h | 7 ++++ arch/arm/include/asm/kvm_vgic.h | 70 +++++++++++++++++++++++++++++++++++++++ arch/arm/kvm/arm.c | 21 +++++++++++- arch/arm/kvm/interrupts.S | 4 ++ arch/arm/kvm/mmio.c | 3 ++ virt/kvm/kvm_main.c | 5 ++- 6 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 arch/arm/include/asm/kvm_vgic.h -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index e66cd56..49ba25a 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -23,6 +23,7 @@ #include #include #include +#include #define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS #define KVM_MEMORY_SLOTS 32 @@ -58,6 +59,9 @@ struct kvm_arch { /* Stage-2 page table */ pgd_t *pgd; + + /* Interrupt controller */ + struct vgic_dist vgic; }; #define KVM_NR_MEM_OBJS 40 @@ -92,6 +96,9 @@ struct kvm_vcpu_arch { struct vfp_hard_struct vfp_guest; struct vfp_hard_struct *vfp_host; + /* VGIC state */ + struct vgic_cpu vgic_cpu; + /* * Anything that is not used directly from assembly code goes * here. diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h new file mode 100644 index 0000000..d75540a --- /dev/null +++ b/arch/arm/include/asm/kvm_vgic.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 ARM Ltd. + * Author: Marc Zyngier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARM_KVM_VGIC_H +#define __ASM_ARM_KVM_VGIC_H + +struct vgic_dist { +}; + +struct vgic_cpu { +}; + +struct kvm; +struct kvm_vcpu; +struct kvm_run; +struct kvm_exit_mmio; + +#ifndef CONFIG_KVM_ARM_VGIC +static inline int kvm_vgic_hyp_init(void) +{ + return 0; +} + +static inline int kvm_vgic_init(struct kvm *kvm) +{ + return 0; +} + +static inline int kvm_vgic_create(struct kvm *kvm) +{ + return 0; +} + +static inline void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) {} +static inline void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu) {} +static inline void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu) {} + +static inline int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) +{ + return 0; +} + +static inline bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, + struct kvm_exit_mmio *mmio) +{ + return false; +} + +static inline int irqchip_in_kernel(struct kvm *kvm) +{ + return 0; +} +#endif + +#endif diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 60b119a..426828a 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -183,6 +183,9 @@ int kvm_dev_ioctl_check_extension(long ext) { int r; switch (ext) { +#ifdef CONFIG_KVM_ARM_VGIC + case KVM_CAP_IRQCHIP: +#endif case KVM_CAP_USER_MEMORY: case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: @@ -304,6 +307,10 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) { /* Force users to call KVM_ARM_VCPU_INIT */ vcpu->arch.target = -1; + + /* Set up VGIC */ + kvm_vgic_vcpu_init(vcpu); + return 0; } @@ -363,7 +370,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, */ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) { - return !!v->arch.irq_lines; + return !!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v); } int kvm_arch_vcpu_in_guest_mode(struct kvm_vcpu *v) @@ -633,6 +640,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) update_vttbr(vcpu->kvm); + kvm_vgic_sync_to_cpu(vcpu); + local_irq_disable(); /* @@ -645,6 +654,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) { local_irq_enable(); + kvm_vgic_sync_from_cpu(vcpu); continue; } @@ -683,6 +693,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) * Back from guest *************************************************************/ + kvm_vgic_sync_from_cpu(vcpu); + ret = handle_exit(vcpu, run, ret); } @@ -965,6 +977,13 @@ static int init_hyp_mode(void) } } + /* + * Init HYP view of VGIC + */ + err = kvm_vgic_hyp_init(); + if (err) + goto out_free_mappings; + return 0; out_free_vfp: free_percpu(kvm_host_vfp_state); diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index 7c89708..e418c9b 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S @@ -91,6 +91,8 @@ ENTRY(__kvm_vcpu_run) save_host_regs + restore_vgic_state r0 + @ Store hardware CP15 state and load guest state read_cp15_state write_cp15_state 1, r0 @@ -184,6 +186,8 @@ after_vfp_restore: read_cp15_state 1, r1 write_cp15_state + save_vgic_state r1 + restore_host_regs clrex @ Clear exclusive monitor bx lr @ return to IOCTL diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c index d6a4ca0..eadec78a 100644 --- a/arch/arm/kvm/mmio.c +++ b/arch/arm/kvm/mmio.c @@ -149,6 +149,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, if (mmio.is_write) memcpy(mmio.data, vcpu_reg(vcpu, rt), mmio.len); + if (vgic_handle_mmio(vcpu, run, &mmio)) + return 1; + kvm_prepare_mmio(run, &mmio); return 0; } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2fb7319..665af96 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1880,12 +1880,13 @@ static long kvm_vcpu_ioctl(struct file *filp, if (vcpu->kvm->mm != current->mm) return -EIO; -#if defined(CONFIG_S390) || defined(CONFIG_PPC) +#if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_ARM) /* * Special cases: vcpu ioctls that are asynchronous to vcpu execution, * so vcpu_load() would break it. */ - if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT) + if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT || + ioctl == KVM_IRQ_LINE) return kvm_arch_vcpu_ioctl(filp, ioctl, arg); #endif