From patchwork Wed Jun 25 09:28:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 32461 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f72.google.com (mail-oa0-f72.google.com [209.85.219.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 08D4B20C88 for ; Wed, 25 Jun 2014 09:29:11 +0000 (UTC) Received: by mail-oa0-f72.google.com with SMTP id eb12sf9073809oac.11 for ; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=nYpymQ9+WmkJJrrGdA/qFUbVb+sJD0yQSioNPGV704U=; b=admRPZqdmuMX8CuPfL9Q1ea3BHATsqW/Fx5MMCEjONtFns00YNJrNNZIRR4MIfpBuX 7YS+1fvzb73RswgB0blq9ilfo+2xDDsBRdeLY/TYsEKnDdkZYJEwXPzzsP1T6pq5Qfn9 oltwnTmToobWXfUDG0REnRvy0Zn0hO2pzBb/tHuK0nJqzasFOzWCoPHBkJw2b4/yAOLB RVQL7JB6l9MUqHUjXjKQMPqStNLXkIM0pmYyBXmJkS40uWTh8Dn6t5A/pnY9dO1QSyrF TZLZDvof4EDbp5mfrUrzqHmrdrgIEL3wzbdyxxK6vnQCgCgYIgzN3iYISgznJaKdvuvz ZOrg== X-Gm-Message-State: ALoCoQkmLAZdWwOETQrzBsGV3ZkBNubRFz6ilAdgRcy8gZMwRXW7TeChjx4XE2LBn8abPA/acEfi X-Received: by 10.182.51.228 with SMTP id n4mr3802774obo.28.1403688551663; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.27.33 with SMTP id 30ls2000396qgw.13.gmail; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) X-Received: by 10.52.117.209 with SMTP id kg17mr3754595vdb.28.1403688551533; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) Received: from mail-ve0-f179.google.com (mail-ve0-f179.google.com [209.85.128.179]) by mx.google.com with ESMTPS id uk3si1889788vec.102.2014.06.25.02.29.11 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 25 Jun 2014 02:29:11 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.179 as permitted sender) client-ip=209.85.128.179; Received: by mail-ve0-f179.google.com with SMTP id sa20so1691655veb.10 for ; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) X-Received: by 10.58.196.231 with SMTP id ip7mr8342vec.47.1403688551454; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp274359vcb; Wed, 25 Jun 2014 02:29:11 -0700 (PDT) X-Received: by 10.68.191.138 with SMTP id gy10mr9586322pbc.169.1403688550706; Wed, 25 Jun 2014 02:29:10 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id tx10si4304573pac.112.2014.06.25.02.29.10; Wed, 25 Jun 2014 02:29:10 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755422AbaFYJ26 (ORCPT + 27 others); Wed, 25 Jun 2014 05:28:58 -0400 Received: from fw-tnat.austin.arm.com ([217.140.110.23]:51339 "EHLO collaborate-mta1.arm.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752091AbaFYJ2z (ORCPT ); Wed, 25 Jun 2014 05:28:55 -0400 Received: from e102391-lin.cambridge.arm.com (e102391-lin.cambridge.arm.com [10.1.209.143]) by collaborate-mta1.arm.com (Postfix) with ESMTP id D517013FA91; Wed, 25 Jun 2014 04:28:53 -0500 (CDT) From: Marc Zyngier To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: Will Deacon , Catalin Marinas , Thomas Gleixner , eric.auger@linaro.org, Christoffer Dall Subject: [RFC PATCH 2/9] genirq: Allow the state of a forwarded irq to be save/restored Date: Wed, 25 Jun 2014 10:28:43 +0100 Message-Id: <1403688530-23273-3-git-send-email-marc.zyngier@arm.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1403688530-23273-1-git-send-email-marc.zyngier@arm.com> References: <1403688530-23273-1-git-send-email-marc.zyngier@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: marc.zyngier@arm.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.179 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , When a peripheral is shared between virtual machines, its interrupt state becomes part of the guest's state, and must be switched accordingly. Introduce a pair of accessors (irq_get_fwd_state/irq_set_fwd_state) to retrieve the bits that can be of interest to KVM: pending, active, and masked. - irq_get_fwd_state returns the state of the interrupt according to a mask containing any of the IRQ_STATE_PENDING, IRQ_STATE_ACTIVE or IRQ_STATE_MASKED bits. - irq_set_fwd_state sets the state of the interrupt according to a similar mask. Only a forwarded interrupt can be manipulated in such a way. Signed-off-by: Marc Zyngier --- include/linux/interrupt.h | 2 ++ include/linux/irq.h | 16 ++++++++++ kernel/irq/manage.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 698ad05..cfb8006 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -361,6 +361,8 @@ static inline int disable_irq_wake(unsigned int irq) return irq_set_irq_wake(irq, 0); } +extern int irq_get_fwd_state(unsigned int irq, u32 *val, u32 mask); +extern int irq_set_fwd_state(unsigned int irq, u32 val, u32 mask); #ifdef CONFIG_IRQ_FORCED_THREADING extern bool force_irqthreads; diff --git a/include/linux/irq.h b/include/linux/irq.h index b4b3120..88ecd58 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -323,6 +323,8 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) * any other callback related to this irq * @irq_release_resources: optional to release resources acquired with * irq_request_resources + * @irq_get_fwd_state: return the state of a forwarded interrupt + * @irq_set_fwd_state: set the state of a forwarded interrupt * @flags: chip specific flags */ struct irq_chip { @@ -359,6 +361,9 @@ struct irq_chip { int (*irq_request_resources)(struct irq_data *data); void (*irq_release_resources)(struct irq_data *data); + u32 (*irq_get_fwd_state)(struct irq_data *data, u32 mask); + void (*irq_set_fwd_state)(struct irq_data *data, u32 val, u32 mask); + unsigned long flags; }; @@ -384,6 +389,17 @@ enum { IRQCHIP_EOI_THREADED = (1 << 6), }; +/* + * irq_get_fwd_state/irq_set_fwd_state specific flags (used for both + * state and mask). Only valid for an interrupt that has the + * IRQD_IRQ_FORWARDED flag. + */ +enum { + IRQ_FWD_STATE_PENDING = (1 << 0), + IRQ_FWD_STATE_ACTIVE = (1 << 1), + IRQ_FWD_STATE_MASKED = (1 << 2), +}; + /* This include will go away once we isolated irq_desc usage to core code */ #include diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 3dc6a61..c42dd73 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1770,3 +1770,83 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler, return retval; } + +/** + * irq_get_fwd_state - return the state of a forwarded interrupt. + * @irq: Interrupt line that is forwarded to a VM + * @val: Pointer where the state is being stored + * @mask: Bitmask of IRQ_FWD_STATE_* the caller wants to know about + * + * This call snapshots the state of a forwarded interrupt, + * depending on the mask which indicates the requested bits. + * + * This function should be called with preemption disabled if the + * interrupt controller has per-cpu registers. + */ +int irq_get_fwd_state(unsigned int irq, u32 *val, u32 mask) +{ + struct irq_desc *desc; + struct irq_data *data; + struct irq_chip *chip; + unsigned long flags; + + desc = irq_to_desc(irq); + if (!desc) + return -EINVAL; + + data = irq_desc_get_irq_data(desc); + if (!irqd_irq_forwarded(data)) + return -EINVAL; + + chip = irq_desc_get_chip(desc); + if (!chip->irq_get_fwd_state) + return -EINVAL; + + chip_bus_lock(desc); + raw_spin_lock_irqsave(&desc->lock, flags); + *val = chip->irq_get_fwd_state(data, mask); + raw_spin_unlock_irqrestore(&desc->lock, flags); + chip_bus_sync_unlock(desc); + + return 0; +} + +/** + * irq_set_fwd_state - set the state of a forwarded interrupt. + * @irq: Interrupt line that is forwarded to a VM + * @val: State to be restored + * @mask: Bitmask of IRQ_FWD_STATE_* defining the valid bits in @val + * + * This call sets the state of a forwarded interrupt, depending + * on the mask which indicates the valid bits. + * + * This function should be called with preemption disabled if the + * interrupt controller has per-cpu registers. + */ +int irq_set_fwd_state(unsigned int irq, u32 val, u32 mask) +{ + struct irq_desc *desc; + struct irq_data *data; + struct irq_chip *chip; + unsigned long flags; + + desc = irq_to_desc(irq); + if (!desc) + return -EINVAL; + + data = irq_desc_get_irq_data(desc); + if (!irqd_irq_forwarded(data)) + return -EINVAL; + + chip = irq_desc_get_chip(desc); + if (!chip->irq_set_fwd_state) + return -EINVAL; + + chip_bus_lock(desc); + raw_spin_lock_irqsave(&desc->lock, flags); + chip->irq_set_fwd_state(data, val, mask); + raw_spin_unlock_irqrestore(&desc->lock, flags); + chip_bus_sync_unlock(desc); + + return 0; +}