From patchwork Thu Mar 22 11:56:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 132265 Delivered-To: patch@linaro.org Received: by 10.46.84.29 with SMTP id i29csp741071ljb; Thu, 22 Mar 2018 04:59:07 -0700 (PDT) X-Google-Smtp-Source: AG47ELv9jraTcVdgXuZbEeAF9z8odN6soUai20zfv2Wvf9yul9dqB9BoVmbyOEMJ2KQ8etUHoXbg X-Received: by 2002:a24:9a45:: with SMTP id l66-v6mr8173828ite.19.1521719947836; Thu, 22 Mar 2018 04:59:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521719947; cv=none; d=google.com; s=arc-20160816; b=i0dI4P4d/sN7R+Qcr0PLI1cXPTwvy9E1msKOib++hV/xOH//tG1Ke/bsHs0QZYTTa5 FV5/4QgrcHVbA7Q6epMRDdAdk0WKURlv4KoMnhjOEubgxwv31lvNefSFIBCbBsX5Rsfj UEsHoEuQ56R+iFoLiEQ5bEb5SpQt8/gUtkHSHkD/rZlHmvPpvhPKdpvCjwGmn+NzOWfz U1zieDTNTOo3+GbnhRW6YQh6bbIRUCjEMa/CmRuD1AXw4vSW3FviX1YfTYI4jBnMwpCt oMOyjm3nivjxaUlbdgCZsSWyuFs73+NsFZ2E9d3upRDNQZHfqWY+C42qXSk/zTgBO7FO 3FZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-unsubscribe:list-id :precedence:subject:references:in-reply-to:message-id:date:to:from :dkim-signature:arc-authentication-results; bh=UE8TxN61fXncXCG9FtFh30xTBOK9KvHgrmWHdQNDNxw=; b=B3lcqWsik6Te2YPuztEZNwiz+f5+2vZ0f1CSzFf04J8f5eEHITwoJWZbnDasmU5tiI FQIGb2dlABW8TQtIQOVP6E5nEwzmja6H0ZBDHCavrGQ4y1z8kcMjTKLQytFohe6i5kD/ N9VKqRjl4zvji0mHC4MMTe45cMuLoGIv7EawqDFQnkzPLZFVScKdPOlAikfphYWd/2R9 4Hdde6quq2UJG8d/3psPWa9RMHZLdo0nS1Vhewzytsy4rN0qjM8r8ZZI7uPYWwZGYcT1 g36p2QvthK36eXvvIFOrGSgVubLDVFJZiCmstIZQeUu04WpWp/69NhkmdP3irBP+JEAF e0FA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=kVK2MK3b; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id 17-v6si5166195itx.56.2018.03.22.04.59.07 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 22 Mar 2018 04:59:07 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=kVK2MK3b; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1eyyqB-0005xp-2E; Thu, 22 Mar 2018 11:57:07 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1eyyq9-0005wG-43 for xen-devel@lists.xenproject.org; Thu, 22 Mar 2018 11:57:05 +0000 X-Inumbo-ID: 186e626d-2dc8-11e8-9728-bc764e045a96 Received: from mail-wm0-x242.google.com (unknown [2a00:1450:400c:c09::242]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 186e626d-2dc8-11e8-9728-bc764e045a96; Thu, 22 Mar 2018 12:56:47 +0100 (CET) Received: by mail-wm0-x242.google.com with SMTP id t6so15615108wmt.5 for ; Thu, 22 Mar 2018 04:57:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zvte5vF9ZK7tlvb0GGV7W0+MriShHCzgfmeVp2YBulk=; b=kVK2MK3bBcD9H5xD3XXuoRu6f+8h160x1aNWiaFt9DoMsbx0EaJK4UkpjxMndwywPN jQXUdGXMXrMPX7Qt8Atoe9n+n91UWExIZHF5CSkSj0Epn9v9H6+iWldiTsHcFEMXxNXR e9XBbSx54K2CZG2zZ7Hrg7+2//a6sUM5REZds= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zvte5vF9ZK7tlvb0GGV7W0+MriShHCzgfmeVp2YBulk=; b=cx5nyot7H57q/v9qvXgh3fO+XbYjCuum/Wkfp0cccPjx4cxoF7n2y9MGeRBK2SeSTF VIn8zpM71kkLD+PRXrQfmKg8ujH1QbqeNkmRW1HiIa5ozFdNyxGMFPTBBJ6z+wnqNn8L 1kadwVyPUAU1EN6UCeF08Z9qamENTQ/+I6+xVegnXgaja5WzqV+IG/rTkI8qOtIN96It 6xpHG4Hl8g/Mo5KcNPVYHs6q+A3BT7NwQnw6W5DNnqLwit04lXs3V0pPEYNMb07s8RxH maiEFVHbGVpjlyEOQufi9rjhZLA33UaCl0pTeKYNPOQ+ElsSExwV/WH2/L3XLYadPgok OAMw== X-Gm-Message-State: AElRT7HyDnm/l7eajhL43QFrMFEzeWCbLAt99vOJUKACHotNWNNcDNNI S4Ki0oOgRUU9513f3OvsKdyYNA== X-Received: by 10.28.9.68 with SMTP id 65mr5452942wmj.29.1521719821465; Thu, 22 Mar 2018 04:57:01 -0700 (PDT) Received: from e104803-lin.lan (mail.andrep.de. [217.160.17.100]) by smtp.gmail.com with ESMTPSA id e67sm12207356wmf.20.2018.03.22.04.57.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 22 Mar 2018 04:57:00 -0700 (PDT) From: Andre Przywara To: Julien Grall , Stefano Stabellini Date: Thu, 22 Mar 2018 11:56:47 +0000 Message-Id: <20180322115649.5283-2-andre.przywara@linaro.org> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180322115649.5283-1-andre.przywara@linaro.org> References: <20180322115649.5283-1-andre.przywara@linaro.org> Subject: [Xen-devel] [PATCH v3a 03/39] ARM: GIC: Allow tweaking the active and pending state of an IRQ X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: xen-devel@lists.xenproject.org MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" When playing around with hardware mapped, level triggered virtual IRQs, there is the need to explicitly set the active or pending state of an interrupt at some point. To prepare the GIC for that, we introduce a set_active_state() and a set_pending_state() function to let the VGIC manipulate the state of an associated hardware IRQ. This takes care of properly setting the _IRQ_INPROGRESS bit. Signed-off-by: Andre Przywara Reviewed-by: Julien Grall Acked-by: Stefano Stabellini --- Changelog v3 ... v3a: - always set/clear _IRQ_INPROGRESS bit (not only for guest IRQs) - add comments Changelog v2 ... v3: - extend comments to note preliminary nature of vgic_get_lpi() Changelog v1 ... v2: - reorder header file inclusion xen/arch/arm/gic-v2.c | 41 +++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic-v3.c | 37 +++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/gic.h | 24 ++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c index aa0fc6c1a1..7374686235 100644 --- a/xen/arch/arm/gic-v2.c +++ b/xen/arch/arm/gic-v2.c @@ -243,6 +243,45 @@ static void gicv2_poke_irq(struct irq_desc *irqd, uint32_t offset) writel_gicd(1U << (irqd->irq % 32), offset + (irqd->irq / 32) * 4); } +/* + * This is forcing the active state of an interrupt, somewhat circumventing + * the normal interrupt flow and the GIC state machine. So use with care + * and only if you know what you are doing. For this reason we also have to + * tinker with the _IRQ_INPROGRESS bit here, since the normal IRQ handler + * will not be involved. + */ +static void gicv2_set_active_state(struct irq_desc *irqd, bool active) +{ + ASSERT(spin_is_locked(&irqd->lock)); + + if ( active ) + { + set_bit(_IRQ_INPROGRESS, &irqd->status); + gicv2_poke_irq(irqd, GICD_ISACTIVER); + } + else + { + clear_bit(_IRQ_INPROGRESS, &irqd->status); + gicv2_poke_irq(irqd, GICD_ICACTIVER); + } +} + +static void gicv2_set_pending_state(struct irq_desc *irqd, bool pending) +{ + ASSERT(spin_is_locked(&irqd->lock)); + + if ( pending ) + { + /* The _IRQ_INPROGRESS bit will be set when the interrupt fires. */ + gicv2_poke_irq(irqd, GICD_ISPENDR); + } + else + { + /* The _IRQ_INPROGRESS remains unchanged. */ + gicv2_poke_irq(irqd, GICD_ICPENDR); + } +} + static void gicv2_set_irq_type(struct irq_desc *desc, unsigned int type) { uint32_t cfg, actual, edgebit; @@ -1278,6 +1317,8 @@ const static struct gic_hw_operations gicv2_ops = { .eoi_irq = gicv2_eoi_irq, .deactivate_irq = gicv2_dir_irq, .read_irq = gicv2_read_irq, + .set_active_state = gicv2_set_active_state, + .set_pending_state = gicv2_set_pending_state, .set_irq_type = gicv2_set_irq_type, .set_irq_priority = gicv2_set_irq_priority, .send_SGI = gicv2_send_SGI, diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index cb41844af2..a5105ac9e7 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -477,6 +477,41 @@ static unsigned int gicv3_read_irq(void) return irq; } +/* + * This is forcing the active state of an interrupt, somewhat circumventing + * the normal interrupt flow and the GIC state machine. So use with care + * and only if you know what you are doing. For this reason we also have to + * tinker with the _IRQ_INPROGRESS bit here, since the normal IRQ handler + * will not be involved. + */ +static void gicv3_set_active_state(struct irq_desc *irqd, bool active) +{ + ASSERT(spin_is_locked(&irqd->lock)); + + if ( active ) + { + set_bit(_IRQ_INPROGRESS, &irqd->status); + gicv3_poke_irq(irqd, GICD_ISACTIVER, false); + } + else + { + clear_bit(_IRQ_INPROGRESS, &irqd->status); + gicv3_poke_irq(irqd, GICD_ICACTIVER, false); + } +} + +static void gicv3_set_pending_state(struct irq_desc *irqd, bool pending) +{ + ASSERT(spin_is_locked(&irqd->lock)); + + if ( pending ) + /* The _IRQ_INPROGRESS bit will be set when the interrupt fires. */ + gicv3_poke_irq(irqd, GICD_ISPENDR, false); + else + /* The _IRQ_INPROGRESS bit will remain unchanged. */ + gicv3_poke_irq(irqd, GICD_ICPENDR, false); +} + static inline uint64_t gicv3_mpidr_to_affinity(int cpu) { uint64_t mpidr = cpu_logical_map(cpu); @@ -1769,6 +1804,8 @@ static const struct gic_hw_operations gicv3_ops = { .eoi_irq = gicv3_eoi_irq, .deactivate_irq = gicv3_dir_irq, .read_irq = gicv3_read_irq, + .set_active_state = gicv3_set_active_state, + .set_pending_state = gicv3_set_pending_state, .set_irq_type = gicv3_set_irq_type, .set_irq_priority = gicv3_set_irq_priority, .send_SGI = gicv3_send_sgi, diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index 3079387e06..2aca243ac3 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -345,6 +345,10 @@ struct gic_hw_operations { void (*deactivate_irq)(struct irq_desc *irqd); /* Read IRQ id and Ack */ unsigned int (*read_irq)(void); + /* Force the active state of an IRQ by accessing the distributor */ + void (*set_active_state)(struct irq_desc *irqd, bool state); + /* Force the pending state of an IRQ by accessing the distributor */ + void (*set_pending_state)(struct irq_desc *irqd, bool state); /* Set IRQ type */ void (*set_irq_type)(struct irq_desc *desc, unsigned int type); /* Set IRQ priority */ @@ -393,6 +397,26 @@ static inline unsigned int gic_get_nr_lrs(void) return gic_hw_ops->info->nr_lrs; } +/* + * Set the active state of an IRQ. This should be used with care, as this + * directly forces the active bit, without considering the GIC state machine. + * For private IRQs this only works for those of the current CPU. + */ +static inline void gic_set_active_state(struct irq_desc *irqd, bool state) +{ + gic_hw_ops->set_active_state(irqd, state); +} + +/* + * Set the pending state of an IRQ. This should be used with care, as this + * directly forces the pending bit, without considering the GIC state machine. + * For private IRQs this only works for those of the current CPU. + */ +static inline void gic_set_pending_state(struct irq_desc *irqd, bool state) +{ + gic_hw_ops->set_pending_state(irqd, state); +} + void register_gic_ops(const struct gic_hw_operations *ops); int gic_make_hwdom_dt_node(const struct domain *d, const struct dt_device_node *gic,