From patchwork Tue Oct 20 17:22:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shlomo Pongratz X-Patchwork-Id: 533110 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2B4C014110C for ; Wed, 21 Oct 2015 05:43:35 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=BCjYgC9P; dkim-atps=neutral Received: from localhost ([::1]:47215 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zoacw-0001o5-Ke for incoming@patchwork.ozlabs.org; Tue, 20 Oct 2015 13:23:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50999) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zoabn-0000X2-GC for qemu-devel@nongnu.org; Tue, 20 Oct 2015 13:22:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zoabm-0003RJ-5m for qemu-devel@nongnu.org; Tue, 20 Oct 2015 13:21:59 -0400 Received: from mail-wi0-x22f.google.com ([2a00:1450:400c:c05::22f]:33115) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zoabl-0003RC-TF for qemu-devel@nongnu.org; Tue, 20 Oct 2015 13:21:58 -0400 Received: by wijp11 with SMTP id p11so58009848wij.0 for ; Tue, 20 Oct 2015 10:21:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qP1XNBVIhsANEew3UH+w4yBMAujop2Ng9Hbsxpk4U+w=; b=BCjYgC9PaCUh15coHdGFHvF1yubVzMHwT4cGkZxiRdtgDecfJgZE9g7rIDtdjoyNfR VJBFAGFwiT+/ic5bz5TxbBLQyP5QjLXdA4ROgu9eP0Jb3L0/EzXrr3JNXnxF6HJGs5UU +3+67OeFwYNAqYZcXK9aG2pFI10XhV1SCf1sX/KXdwzXKGIAVFVCtX1LRpiWJzaUsTBJ Ll6URi1tQO7AbqAmQcr9Ts3lMEB1QndXonQlmcKZFzoXvREv4X1lC2DZmNkq1sKu6qUP 7S8zqo4+Z0scGXQJQL6zP76p9kPHeWiJ/0/cdkhWf3K0IwCT07ekH/mZyz+mTZN+4t6F mjDA== X-Received: by 10.194.133.105 with SMTP id pb9mr6114048wjb.158.1445361717314; Tue, 20 Oct 2015 10:21:57 -0700 (PDT) Received: from localhost.localdomain (bzq-79-181-26-227.red.bezeqint.net. [79.181.26.227]) by smtp.gmail.com with ESMTPSA id jd9sm3771828wic.0.2015.10.20.10.21.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 20 Oct 2015 10:21:56 -0700 (PDT) From: Shlomo Pongratz To: qemu-devel@nongnu.org Date: Tue, 20 Oct 2015 20:22:06 +0300 Message-Id: <1445361732-16257-4-git-send-email-shlomopongratz@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1445361732-16257-1-git-send-email-shlomopongratz@gmail.com> References: <1445361732-16257-1-git-send-email-shlomopongratz@gmail.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c05::22f Cc: peter.maydell@linaro.org, eric.auger@linaro.org, Shlomo Pongratz , p.fedin@samsung.com, shannon.zhao@linaro.org, ashoks@broadcom.com, imammedo@redhat.com Subject: [Qemu-devel] [PATCH RFC V5 3/9] hw/intc: arm_gicv3_cpu_interface X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Shlomo Pongratz This patch incudes the GIC functionality that is exposed to the CPU via system instructions. In GICv2 this functionality was exposed via memory mapped access. Signed-off-by: Shlomo Pongratz --- hw/intc/Makefile.objs | 1 + hw/intc/arm_gicv3_cpu_interface.c | 130 ++++++++++++++++++++++++++++++++++++++ hw/intc/arm_gicv3_cpu_interface.h | 21 ++++++ hw/intc/gicv3_internal.h | 6 ++ 4 files changed, 158 insertions(+) create mode 100644 hw/intc/arm_gicv3_cpu_interface.c create mode 100644 hw/intc/arm_gicv3_cpu_interface.h diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index e8cdd27..fb6494f 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -14,6 +14,7 @@ common-obj-$(CONFIG_ARM_GIC) += arm_gic.o common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_interrupts.o +common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpu_interface.o common-obj-$(CONFIG_OPENPIC) += openpic.o obj-$(CONFIG_APIC) += apic.o apic_common.o diff --git a/hw/intc/arm_gicv3_cpu_interface.c b/hw/intc/arm_gicv3_cpu_interface.c new file mode 100644 index 0000000..ba5ee38 --- /dev/null +++ b/hw/intc/arm_gicv3_cpu_interface.c @@ -0,0 +1,130 @@ +#include "gicv3_internal.h" +#include "qom/cpu.h" +#include "arm_gicv3_cpu_interface.h" +#include "arm_gicv3_interrupts.h" + +/* Cuurently no GICv2 backwards compatibility (no memory mapped regs) + * Uses system registers mode. + */ +const int gicv3_no_gicv2_bc = 1; +uint32_t gicv3_sre; + +void armv8_gicv3_set_sgi(void *opaque, int cpuindex, uint64_t value) +{ + GICv3State *s = (GICv3State *) opaque; + int irq, i; + + /* Page 2227 ICC_SGI1R_EL1 */ + + irq = (value >> 24) & 0xf; + + /* The external routines use the hardware vector numbering, ie. the first + * IRQ is #16. The internal GIC routines use #32 as the first IRQ. + */ + if (irq >= 16) + irq += 16; + + /* IRM bit */ + if (value & (1ll << 40)) { + /* Send to all the cores exclude self */ + for (i = 0; i < cpuindex; i++) { + set_bit(cpuindex, s->sgi[irq].state[i].pending); + } + for (i = cpuindex + 1; i < s->num_cpu; i++) { + set_bit(cpuindex, s->sgi[irq].state[i].pending); + } + /* GIC_SET_PENDING(irq, (ALL_CPU_MASK & ~cm)); */ + bitmap_fill(s->irq_state[irq].pending, s->num_cpu); + clear_bit(cpuindex, s->irq_state[irq].pending); + DPRINTF("cpu(%d) sends irq(%d) to ALL exclude self\n", cpuindex, irq); + } else { + /* Find linear of first core in cluster. See page 2227 ICC_SGI1R_EL1 + * With our GIC-500 implementation we can have 16 clusters of 8 cpu each + */ + uint64_t target_affinity; + uint64_t target_list; + target_affinity = (value >> (16 - ARM_AFF1_SHIFT)) & ARM_AFF1_MASK; + target_affinity |= (value >> (32 - ARM_AFF2_SHIFT)) & ARM_AFF2_MASK; + target_affinity |= (value >> (48 - ARM_AFF3_SHIFT)) & ARM_AFF3_MASK; + target_list = value & 0xff; + + for (i = 0; i < s->num_cpu; i++) { + uint64_t cpu_aff0 = s->mp_affinity[i] & ARM_AFF0_MASK; + uint64_t cpu_aff123 = s->mp_affinity[i] & ~ARM_AFF0_MASK; + if (cpu_aff123 == target_affinity && + ((1 << cpu_aff0) & target_list)) { + set_bit(cpuindex, s->sgi[irq].state[i].pending); + GIC_SET_PENDING(irq, i); + } + } + } + gicv3_update(s); +} + +uint64_t armv8_gicv3_acknowledge_irq(void *opaque, int cpuindex, + MemTxAttrs attrs) +{ + GICv3State *s = (GICv3State *) opaque; + return gicv3_acknowledge_irq(s, cpuindex, attrs); +} + +void armv8_gicv3_complete_irq(void *opaque, int cpuindex, int irq, + MemTxAttrs attrs) +{ + GICv3State *s = (GICv3State *) opaque; + irq &= 0xffffff; + gicv3_complete_irq(s, cpuindex, irq, attrs); +} + +uint64_t armv8_gicv3_get_priority_mask(void *opaque, int cpuindex) +{ + GICv3State *s = (GICv3State *) opaque; + return s->priority_mask[cpuindex]; +} + +void armv8_gicv3_set_priority_mask(void *opaque, int cpuindex, uint32_t mask) +{ + GICv3State *s = (GICv3State *) opaque; + s->priority_mask[cpuindex] = mask & 0xff; + DPRINTF("%s cpu(%d) priority mask 0x%x\n", + __func__, cpuindex, s->priority_mask[cpuindex]); + gicv3_update(s); +} + +uint64_t armv8_gicv3_get_sre(void *opaque) +{ + /* Uses only system registers, no memory mapped access GICv2 mode */ + return gicv3_sre; +} + +void armv8_gicv3_set_sre(void *opaque, uint64_t sre) +{ + if (!(sre & 1) && gicv3_no_gicv2_bc) { + /* Cuurently no GICv2 backwards compatibility (no memory mapped regs) + * Uses system registers mode + */ + DPRINTF("Try to use memory mapped interface sre(0x%lx)\n", sre); + assert(0); + } + gicv3_sre = sre; +} + +uint64_t armv8_gicv3_get_igrpen1(void *opaque, int cpuindex) +{ + GICv3State *s = (GICv3State *) opaque; + return !!(s->cpu_ctlr[cpuindex] & GICC_CTLR_EN_GRP1); +} + +void armv8_gicv3_set_igrpen1(void *opaque, int cpuindex, uint64_t igrpen1) +{ + GICv3State *s = (GICv3State *) opaque; + if (igrpen1) + s->cpu_ctlr[cpuindex] |= GICC_CTLR_EN_GRP1; + else + s->cpu_ctlr[cpuindex] &= ~GICC_CTLR_EN_GRP1; + + DPRINTF("CPU Interface %d: Group0 Interrupts %sabled, " + "Group1 Interrupts %sabled\n", cpuindex, + (s->cpu_ctlr[cpuindex] & GICC_CTLR_EN_GRP0) ? "En" : "Dis", + (s->cpu_ctlr[cpuindex] & GICC_CTLR_EN_GRP1) ? "En" : "Dis"); +} diff --git a/hw/intc/arm_gicv3_cpu_interface.h b/hw/intc/arm_gicv3_cpu_interface.h new file mode 100644 index 0000000..fb03c2c --- /dev/null +++ b/hw/intc/arm_gicv3_cpu_interface.h @@ -0,0 +1,21 @@ +#ifndef QEMU_ARM_GICV3_CPU_INTERFACE_H +#define QEMU_ARM_GICV3_CPU_INTERFACE_H + + +/* These routines are called from cpu64.c and are defined in target-arm/cpu.h + * like armv7m_nvic_XXX routines. + * I couldn't find how to include it without compilation errors + */ +void armv8_gicv3_set_sgi(void *opaque, int cpuindex, uint64_t value); +uint64_t armv8_gicv3_acknowledge_irq(void *opaque, int cpuindex, + MemTxAttrs attrs); +void armv8_gicv3_complete_irq(void *opaque, int cpuindex, int irq, + MemTxAttrs attrs); +uint64_t armv8_gicv3_get_priority_mask(void *opaque, int cpuindex); +void armv8_gicv3_set_priority_mask(void *opaque, int cpuindex, uint32_t mask); +uint64_t armv8_gicv3_get_sre(void *opaque); +void armv8_gicv3_set_sre(void *opaque, uint64_t sre); +uint64_t armv8_gicv3_get_igrpen1(void *opaque, int cpuindex); +void armv8_gicv3_set_igrpen1(void *opaque, int cpuindex, uint64_t igrpen1); + +#endif /* !QEMU_ARM_GIC_CPU_INTERFACE_H */ diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 362455c..14915e0 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -217,6 +217,12 @@ static inline bool gic_has_groups(GICv3State *s) return 1; } +/* Cuurently no GICv2 backwards compatibility (no memory mapped regs) + * Uses system registers mode. + */ +extern const int gicv3_no_gicv2_bc; +extern uint32_t gicv3_sre; + #undef DEBUG_GICV3 #ifdef DEBUG_GICV3