From patchwork Thu Apr 1 02:41:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176963 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F7C1C433ED for ; Thu, 1 Apr 2021 02:43:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F104161059 for ; Thu, 1 Apr 2021 02:43:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F104161059 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43424 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnJ1-0004RI-0O for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:43:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58354) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHU-0002e2-5c for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:00 -0400 Received: from mail-qv1-xf2d.google.com ([2607:f8b0:4864:20::f2d]:40521) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHQ-00036r-5W for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:41:59 -0400 Received: by mail-qv1-xf2d.google.com with SMTP id c3so365029qvz.7 for ; Wed, 31 Mar 2021 19:41:55 -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 :mime-version:content-transfer-encoding; bh=jIBfB7qhVW2MaDPvfEf0+sBd9P17/mAJTfMOOYVPBzE=; b=wCrfBtUc0JhF98I+Cw6xt71dtzQ+Nw+KxGkSCzPCq9SgOcBb4uTNdxAFMx+zjeYlUb j61F1LE9C1la1tbCAAmME+i2iChZjPjjNJyQWypmrQG3ponXDi3r/HSwhkde6wjO/yGp JEpHB8fPAGBjqcOXbqc6x81JS6uEK2d7vlSkXf8+3aT93/hp5+8ZQygmPXkBC7dEdRcl c65FdllSWR9I4lt/aTJOkgT2/jFClJayAjoHgYjRpohYmPkMtspmiN1xJLsmNA91OGoe fbzKM4XCf5Kkfyh55xvgNTvUbShSNGxu8knLJXdLZcbU1YRkbvbJOuZt4fApN3Ce4O3V Mqbg== 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:mime-version:content-transfer-encoding; bh=jIBfB7qhVW2MaDPvfEf0+sBd9P17/mAJTfMOOYVPBzE=; b=NP4HXHRRsD/XCZpnp83tT/63uuMJhQeha/gzwpnSowXR3QEa/9kvImwPo6Vm+Ato/i xh/EG7ezS7u+CxoyzDwyDNK8KA/Vq7JdSe36f3TxK4SxsWbKtNAEFmACZDIr3bmcralD EN6jI07YmU0Aqz1m11tRI5rMGEXFMRqhdT40TGfSOvaqJL5UeSnRcIGevquIDwtOBB+P SUpJ8m6ljz7EOkG0xuwDvy6yEBF8Kgtl71OVDiC2JXrXmZ5epjKV5rNFVxZVf40bOknn wUdT178h/GtLmkGa60zzkFjtpUMf86/RPSQIcK09Mik2RVpqGWxeVeRLeEshbukMzzRR NiIQ== X-Gm-Message-State: AOAM530vWAmfRb4S2QFO4f2dMOVf8XanMkQsaNqQec+q3nDhGQeZYzA6 E+clMtZYabO3OiXnv/9JAZeK9g== X-Google-Smtp-Source: ABdhPJwWHPBuqV7fzv6b4NB/TOMhymVbAXKTow4p2bh7pSR26/q3MLNnN+++JBnq24GZLF57V/3ajw== X-Received: by 2002:a05:6214:a91:: with SMTP id ev17mr6128707qvb.59.1617244915195; Wed, 31 Mar 2021 19:41:55 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:54 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 1/8] hw/intc: GICv3 ITS initial framework Date: Wed, 31 Mar 2021 22:41:45 -0400 Message-Id: <20210401024152.203896-2-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::f2d; envelope-from=shashi.mallela@linaro.org; helo=mail-qv1-xf2d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Added register definitions relevant to ITS,implemented overall ITS device framework with stubs for ITS control and translater regions read/write,extended ITS common to handle mmio init between existing kvm device and newer qemu device. Signed-off-by: Shashi Mallela --- hw/intc/arm_gicv3_its.c | 334 +++++++++++++++++++++++++ hw/intc/arm_gicv3_its_common.c | 12 +- hw/intc/arm_gicv3_its_kvm.c | 2 +- hw/intc/gicv3_internal.h | 86 ++++++- hw/intc/meson.build | 1 + include/hw/intc/arm_gicv3_its_common.h | 12 +- 6 files changed, 430 insertions(+), 17 deletions(-) create mode 100644 hw/intc/arm_gicv3_its.c diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c new file mode 100644 index 0000000000..209120d102 --- /dev/null +++ b/hw/intc/arm_gicv3_its.c @@ -0,0 +1,334 @@ +/* + * ITS emulation for a GICv3-based system + * + * Copyright Linaro.org 2021 + * + * Authors: + * Shashi Mallela + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/qdev-properties.h" +#include "hw/intc/arm_gicv3_its_common.h" +#include "gicv3_internal.h" +#include "qom/object.h" + +typedef struct GICv3ITSClass GICv3ITSClass; +/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */ +DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass, + ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS) + +struct GICv3ITSClass { + GICv3ITSCommonClass parent_class; + void (*parent_reset)(DeviceState *dev); +}; + +static MemTxResult its_trans_writew(GICv3ITSState *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) +{ + MemTxResult result = MEMTX_OK; + + return result; +} + +static MemTxResult its_trans_writel(GICv3ITSState *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) +{ + MemTxResult result = MEMTX_OK; + + return result; +} + +static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, + uint64_t data, unsigned size, MemTxAttrs attrs) +{ + GICv3ITSState *s = (GICv3ITSState *)opaque; + MemTxResult result; + + switch (size) { + case 2: + result = its_trans_writew(s, offset, data, attrs); + break; + case 4: + result = its_trans_writel(s, offset, data, attrs); + break; + default: + result = MEMTX_ERROR; + break; + } + + if (result == MEMTX_ERROR) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); + /* + * The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + result = MEMTX_OK; + } + return result; +} + +static MemTxResult gicv3_its_translation_read(void *opaque, hwaddr offset, + uint64_t *data, unsigned size, MemTxAttrs attrs) +{ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid read from translation register area at offset " + TARGET_FMT_plx "\n", __func__, offset); + return MEMTX_ERROR; +} + +static MemTxResult its_writeb(GICv3ITSState *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) +{ + qemu_log_mask(LOG_UNIMP, + "%s: unsupported byte write to register at offset " + TARGET_FMT_plx "\n", __func__, offset); + return MEMTX_ERROR; +} + +static MemTxResult its_readb(GICv3ITSState *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) +{ + qemu_log_mask(LOG_UNIMP, + "%s: unsupported byte read from register at offset " + TARGET_FMT_plx "\n", __func__, offset); + return MEMTX_ERROR; +} + +static MemTxResult its_writew(GICv3ITSState *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) +{ + qemu_log_mask(LOG_UNIMP, + "%s: unsupported word write to register at offset " + TARGET_FMT_plx "\n", __func__, offset); + return MEMTX_ERROR; +} + +static MemTxResult its_readw(GICv3ITSState *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) +{ + qemu_log_mask(LOG_UNIMP, + "%s: unsupported word read from register at offset " + TARGET_FMT_plx "\n", __func__, offset); + return MEMTX_ERROR; +} + +static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) +{ + MemTxResult result = MEMTX_OK; + + return result; +} + +static MemTxResult its_readl(GICv3ITSState *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) +{ + MemTxResult result = MEMTX_OK; + + return result; +} + +static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) +{ + MemTxResult result = MEMTX_OK; + + return result; +} + +static MemTxResult its_readll(GICv3ITSState *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) +{ + MemTxResult result = MEMTX_OK; + + return result; +} + +static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data, + unsigned size, MemTxAttrs attrs) +{ + GICv3ITSState *s = (GICv3ITSState *)opaque; + MemTxResult result; + + switch (size) { + case 1: + result = its_readb(s, offset, data, attrs); + break; + case 2: + result = its_readw(s, offset, data, attrs); + break; + case 4: + result = its_readl(s, offset, data, attrs); + break; + case 8: + result = its_readll(s, offset, data, attrs); + break; + default: + result = MEMTX_ERROR; + break; + } + + if (result == MEMTX_ERROR) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest read at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); + /* + * The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + result = MEMTX_OK; + *data = 0; + } + return result; +} + +static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size, MemTxAttrs attrs) +{ + GICv3ITSState *s = (GICv3ITSState *)opaque; + MemTxResult result; + + switch (size) { + case 1: + result = its_writeb(s, offset, data, attrs); + break; + case 2: + result = its_writew(s, offset, data, attrs); + break; + case 4: + result = its_writel(s, offset, data, attrs); + break; + case 8: + result = its_writell(s, offset, data, attrs); + break; + default: + result = MEMTX_ERROR; + break; + } + + if (result == MEMTX_ERROR) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); + /* + * The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + result = MEMTX_OK; + } + return result; +} + +static const MemoryRegionOps gicv3_its_control_ops = { + .read_with_attrs = gicv3_its_read, + .write_with_attrs = gicv3_its_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static const MemoryRegionOps gicv3_its_translation_ops = { + .read_with_attrs = gicv3_its_translation_read, + .write_with_attrs = gicv3_its_translation_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void gicv3_arm_its_realize(DeviceState *dev, Error **errp) +{ + GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev); + + gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops); +} + +static void gicv3_its_reset(DeviceState *dev) +{ + GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev); + GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s); + + if (s->gicv3->cpu->gicr_typer & GICR_TYPER_PLPIS) { + c->parent_reset(dev); + + /* set the ITS default features supported */ + s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, + GITS_TYPE_PHYSICAL); + s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE, + ITS_ITT_ENTRY_SIZE); + s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS); + s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS); + s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1); + s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS); + + /* + * We claim to be an ARM r0p0 with a zero ProductID. + * This is the same as an r0p0 GIC-500. + */ + s->iidr = gicv3_iidr(); + + /* Quiescent bit reset to 1 */ + s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1); + + /* + * setting GITS_BASER0.Type = 0b001 (Device) + * GITS_BASER1.Type = 0b100 (Collection Table) + * GITS_BASER.Type,where n = 3 to 7 are 0b00 (Unimplemented) + * GITS_BASER<0,1>.Page_Size = 64KB + * and default translation table entry size to 16 bytes + */ + s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE, + GITS_ITT_TYPE_DEVICE); + s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE, + GITS_BASER_PAGESIZE_64K); + s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE, + GITS_DTE_SIZE); + + s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE, + GITS_ITT_TYPE_COLLECTION); + s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE, + GITS_BASER_PAGESIZE_64K); + s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE, + GITS_CTE_SIZE); + } +} + +static Property gicv3_its_props[] = { + DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3", + GICv3State *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void gicv3_its_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass); + + dc->realize = gicv3_arm_its_realize; + device_class_set_props(dc, gicv3_its_props); + device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset); +} + +static const TypeInfo gicv3_its_info = { + .name = TYPE_ARM_GICV3_ITS, + .parent = TYPE_ARM_GICV3_ITS_COMMON, + .instance_size = sizeof(GICv3ITSState), + .class_init = gicv3_its_class_init, + .class_size = sizeof(GICv3ITSClass), +}; + +static void gicv3_its_register_types(void) +{ + type_register_static(&gicv3_its_info); +} + +type_init(gicv3_its_register_types) diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c index 66c4c6a188..80cc9ec6d8 100644 --- a/hw/intc/arm_gicv3_its_common.c +++ b/hw/intc/arm_gicv3_its_common.c @@ -50,12 +50,16 @@ static int gicv3_its_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_its = { .name = "arm_gicv3_its", + .version_id = 1, + .minimum_version_id = 1, .pre_save = gicv3_its_pre_save, .post_load = gicv3_its_post_load, .priority = MIG_PRI_GICV3_ITS, .fields = (VMStateField[]) { VMSTATE_UINT32(ctlr, GICv3ITSState), + VMSTATE_UINT32(translater, GICv3ITSState), VMSTATE_UINT32(iidr, GICv3ITSState), + VMSTATE_UINT64(typer, GICv3ITSState), VMSTATE_UINT64(cbaser, GICv3ITSState), VMSTATE_UINT64(cwriter, GICv3ITSState), VMSTATE_UINT64(creadr, GICv3ITSState), @@ -99,15 +103,16 @@ static const MemoryRegionOps gicv3_its_trans_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops) +void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops, + const MemoryRegionOps *tops) { SysBusDevice *sbd = SYS_BUS_DEVICE(s); memory_region_init_io(&s->iomem_its_cntrl, OBJECT(s), ops, s, "control", ITS_CONTROL_SIZE); memory_region_init_io(&s->iomem_its_translation, OBJECT(s), - &gicv3_its_trans_ops, s, - "translation", ITS_TRANS_SIZE); + tops ? tops : &gicv3_its_trans_ops, s, + "translation", ITS_TRANS_SIZE); /* Our two regions are always adjacent, therefore we now combine them * into a single one in order to make our users' life easier. @@ -130,6 +135,7 @@ static void gicv3_its_common_reset(DeviceState *dev) s->cwriter = 0; s->creadr = 0; s->iidr = 0; + s->translater = 0; memset(&s->baser, 0, sizeof(s->baser)); } diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c index b554d2ede0..0b4cbed28b 100644 --- a/hw/intc/arm_gicv3_its_kvm.c +++ b/hw/intc/arm_gicv3_its_kvm.c @@ -106,7 +106,7 @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp) kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0); - gicv3_its_init_mmio(s, NULL); + gicv3_its_init_mmio(s, NULL, NULL); if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS, GITS_CTLR)) { diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 05303a55c8..96cfe2dff9 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -24,6 +24,7 @@ #ifndef QEMU_ARM_GICV3_INTERNAL_H #define QEMU_ARM_GICV3_INTERNAL_H +#include "hw/registerfields.h" #include "hw/intc/arm_gicv3_common.h" /* Distributor registers, as offsets from the distributor base address */ @@ -67,6 +68,9 @@ #define GICD_CTLR_E1NWF (1U << 7) #define GICD_CTLR_RWP (1U << 31) +/* 16 bits EventId */ +#define GICD_TYPER_IDBITS 0xf + /* * Redistributor frame offsets from RD_base */ @@ -122,18 +126,6 @@ #define GICR_WAKER_ProcessorSleep (1U << 1) #define GICR_WAKER_ChildrenAsleep (1U << 2) -#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK (7ULL << 56) -#define GICR_PROPBASER_ADDR_MASK (0xfffffffffULL << 12) -#define GICR_PROPBASER_SHAREABILITY_MASK (3U << 10) -#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7) -#define GICR_PROPBASER_IDBITS_MASK (0x1f) - -#define GICR_PENDBASER_PTZ (1ULL << 62) -#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK (7ULL << 56) -#define GICR_PENDBASER_ADDR_MASK (0xffffffffULL << 16) -#define GICR_PENDBASER_SHAREABILITY_MASK (3U << 10) -#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7) - #define ICC_CTLR_EL1_CBPR (1U << 0) #define ICC_CTLR_EL1_EOIMODE (1U << 1) #define ICC_CTLR_EL1_PMHE (1U << 6) @@ -239,6 +231,76 @@ #define ICH_VTR_EL2_PREBITS_SHIFT 26 #define ICH_VTR_EL2_PRIBITS_SHIFT 29 +/* ITS Registers */ + +FIELD(GITS_BASER, SIZE, 0, 8) +FIELD(GITS_BASER, PAGESIZE, 8, 2) +FIELD(GITS_BASER, SHAREABILITY, 10, 2) +FIELD(GITS_BASER, PHYADDR, 12, 36) +FIELD(GITS_BASER, PHYADDRL_64K, 16, 32) +FIELD(GITS_BASER, PHYADDRH_64K, 48, 4) +FIELD(GITS_BASER, ENTRYSIZE, 48, 5) +FIELD(GITS_BASER, OUTERCACHE, 53, 3) +FIELD(GITS_BASER, TYPE, 56, 3) +FIELD(GITS_BASER, INNERCACHE, 59, 3) +FIELD(GITS_BASER, INDIRECT, 62, 1) +FIELD(GITS_BASER, VALID, 63, 1) + +#define GITS_BASER_PAGESIZE_4K 0 +#define GITS_BASER_PAGESIZE_16K 1 +#define GITS_BASER_PAGESIZE_64K 2 + +#define GITS_ITT_TYPE_DEVICE 1ULL +#define GITS_ITT_TYPE_COLLECTION 4ULL + +FIELD(GITS_CTLR, QUIESCENT, 31, 1) + +FIELD(GITS_TYPER, PHYSICAL, 0, 1) +FIELD(GITS_TYPER, ITT_ENTRY_SIZE, 4, 4) +FIELD(GITS_TYPER, IDBITS, 8, 5) +FIELD(GITS_TYPER, DEVBITS, 13, 5) +FIELD(GITS_TYPER, SEIS, 18, 1) +FIELD(GITS_TYPER, PTA, 19, 1) +FIELD(GITS_TYPER, CIDBITS, 32, 4) +FIELD(GITS_TYPER, CIL, 36, 1) + +/** + * Default features advertised by this version of ITS + */ +/* Physical LPIs supported */ +#define GITS_TYPE_PHYSICAL (1U << 0) + +/* + * 11 bytes Interrupt translation Table Entry size + * Valid = 1 bit,InterruptType = 1 bit, + * Size of LPI number space[considering max 24 bits], + * Size of LPI number space[considering max 24 bits], + * ICID = 16 bits, + * vPEID = 16 bits + */ +#define ITS_ITT_ENTRY_SIZE 0xB + +/* 16 bits EventId */ +#define ITS_IDBITS GICD_TYPER_IDBITS + +/* 16 bits DeviceId */ +#define ITS_DEVBITS 0xF + +/* 16 bits CollectionId */ +#define ITS_CIDBITS 0xF + +/* + * 8 bytes Device Table Entry size + * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits + */ +#define GITS_DTE_SIZE (0x8ULL) + +/* + * 8 bytes Collection Table Entry size + * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE) + */ +#define GITS_CTE_SIZE (0x8ULL) + /* Special interrupt IDs */ #define INTID_SECURE 1020 #define INTID_NONSECURE 1021 diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 1c299039f6..53472239f0 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -8,6 +8,7 @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files( 'arm_gicv3_dist.c', 'arm_gicv3_its_common.c', 'arm_gicv3_redist.c', + 'arm_gicv3_its.c', )) softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c')) softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c')) diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 5a0952b404..08bc5652ed 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -25,17 +25,24 @@ #include "hw/intc/arm_gicv3_common.h" #include "qom/object.h" +#define TYPE_ARM_GICV3_ITS "arm-gicv3-its" + #define ITS_CONTROL_SIZE 0x10000 #define ITS_TRANS_SIZE 0x10000 #define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE) #define GITS_CTLR 0x0 #define GITS_IIDR 0x4 +#define GITS_TYPER 0x8 #define GITS_CBASER 0x80 #define GITS_CWRITER 0x88 #define GITS_CREADR 0x90 #define GITS_BASER 0x100 +#define GITS_TRANSLATER 0x0040 + +#define GITS_PIDR2 0xFFE8 + struct GICv3ITSState { SysBusDevice parent_obj; @@ -52,6 +59,8 @@ struct GICv3ITSState { /* Registers */ uint32_t ctlr; uint32_t iidr; + uint32_t translater; + uint64_t typer; uint64_t cbaser; uint64_t cwriter; uint64_t creadr; @@ -62,7 +71,8 @@ struct GICv3ITSState { typedef struct GICv3ITSState GICv3ITSState; -void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops); +void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops, + const MemoryRegionOps *tops); #define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common" typedef struct GICv3ITSCommonClass GICv3ITSCommonClass; From patchwork Thu Apr 1 02:41:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176965 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F4EDC433B4 for ; Thu, 1 Apr 2021 02:43:38 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C57B861059 for ; Thu, 1 Apr 2021 02:43:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C57B861059 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43628 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnJ2-0004Vx-Tz for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:43:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58366) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHV-0002gP-6Q for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:01 -0400 Received: from mail-qk1-x72e.google.com ([2607:f8b0:4864:20::72e]:34307) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHQ-00037i-Vw for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:00 -0400 Received: by mail-qk1-x72e.google.com with SMTP id g20so933743qkk.1 for ; Wed, 31 Mar 2021 19:41:56 -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 :mime-version:content-transfer-encoding; bh=f8rJ40ECxRHqo1oLNI78S+uMTmTvVDhyimY6qm14khE=; b=dbVJnfuCFBVplsAcIPrmgylBwpwkPH9fmUEqy8hkHWgnWLcUy+Rvg5BLrQ0R0Pa8YK Udsr9vZRsuAnAOGrw3dID8yLGJGcvywWjPA7R53lJHWaHgQAbNerxafuSDcqOuBvO4VJ /aswkSpL9RSl75rrBxWQMokD3VRMz8kHgskFZKoOHNZt0tNmIzNLivV+BYPhd9H4HjbJ yVJGpO83m0Lq/briM6ex48gVVXd/h9UTWy/5/wFH02W7QiOZduLgQpTncfGATht5a0RD M0DocDSWcE7XMTQ3eeTIfn7NBwqHBFojsXGX+hTlwuJN6hDIuS+4+phxh/4oSBcwiHim EFfQ== 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:mime-version:content-transfer-encoding; bh=f8rJ40ECxRHqo1oLNI78S+uMTmTvVDhyimY6qm14khE=; b=Phq9LWdEFDk6dQKKnZR6iAUZ7ag3wNwSjSeMwEf15n1N1mRz2ayd9rL9oMTLHfGUAf xmFlF1X109jJ6DVck93YqtKU1nAGq3lEXGeMrmRpmVPi3fszVIEF6knnzIr4PV80tV8P PoOObwXuJVtkiiJLVUhHuSskJ1h4LZOD7ScdirGljH+OS01jaV1sYJpRARmOsYnXssei raFPaUJfYVHge80OS0986+dQP+a86Ww84Hrw1/xZYpDrHrX7na9uD1yS/HHoGmXjXNoI rGv/pYYbOhVF1pIzncCJ2IYfif4yUDH7NxSUJXWhDgyQu08cPtpLHDOn/rfbkY0AKj2N kptQ== X-Gm-Message-State: AOAM530cMJI8DanmMsyVpfXBPSIrkbVzd4EQ6md+kcsRSvn5IxWyUNh9 hqWl1GZs9eWejEit0T+pazFoCQ== X-Google-Smtp-Source: ABdhPJwFWAA05oTiemZHKe++Us+aBd7bQNedOAi/fv7G2jW216HsMIF5RyLGAOGBnVVb95sMFPg17Q== X-Received: by 2002:a37:a48c:: with SMTP id n134mr6453326qke.490.1617244915886; Wed, 31 Mar 2021 19:41:55 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:55 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 2/8] hw/intc: GICv3 ITS register definitions added Date: Wed, 31 Mar 2021 22:41:46 -0400 Message-Id: <20210401024152.203896-3-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::72e; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x72e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Defined descriptors for ITS device table,collection table and ITS command queue entities.Implemented register read/write functions, extract ITS table parameters and command queue parameters,extended gicv3 common to capture qemu address space(which host the ITS table platform memories required for subsequent ITS processing) and initialize the same in its device. Signed-off-by: Shashi Mallela --- hw/intc/arm_gicv3_its.c | 313 +++++++++++++++++++++++++ hw/intc/arm_gicv3_its_common.c | 42 ++++ hw/intc/gicv3_internal.h | 33 ++- include/hw/intc/arm_gicv3_common.h | 4 + include/hw/intc/arm_gicv3_its_common.h | 28 +++ 5 files changed, 414 insertions(+), 6 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 209120d102..81373f049d 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -28,6 +28,131 @@ struct GICv3ITSClass { void (*parent_reset)(DeviceState *dev); }; +static bool extract_table_params(GICv3ITSState *s, int index) +{ + uint16_t num_pages = 0; + uint8_t page_sz_type; + uint8_t type; + uint32_t page_sz = 0; + uint64_t value = s->baser[index]; + + num_pages = FIELD_EX64(value, GITS_BASER, SIZE); + page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE); + + if (page_sz_type == 0) { + page_sz = GITS_ITT_PAGE_SIZE_0; + } else if (page_sz_type == 0) { + page_sz = GITS_ITT_PAGE_SIZE_1; + } else if (page_sz_type == 2) { + page_sz = GITS_ITT_PAGE_SIZE_2; + } else { + return false; + } + + type = FIELD_EX64(value, GITS_BASER, TYPE); + + if (type == GITS_ITT_TYPE_DEVICE) { + s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); + + if (s->dt.valid) { + s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); + s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); + + if (!s->dt.indirect) { + s->dt.max_entries = ((num_pages + 1) * page_sz) / + s->dt.entry_sz; + } else { + s->dt.max_entries = ((((num_pages + 1) * page_sz) / + L1TABLE_ENTRY_SIZE) * + (page_sz / s->dt.entry_sz)); + } + + s->dt.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, + DEVBITS) + 1)); + + if ((page_sz == GITS_ITT_PAGE_SIZE_0) || + (page_sz == GITS_ITT_PAGE_SIZE_1)) { + s->dt.base_addr = FIELD_EX64(value, GITS_BASER, PHYADDR); + s->dt.base_addr <<= R_GITS_BASER_PHYADDR_SHIFT; + } else if (page_sz == GITS_ITT_PAGE_SIZE_2) { + s->dt.base_addr = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << + R_GITS_BASER_PHYADDRL_64K_SHIFT; + s->dt.base_addr |= ((value >> R_GITS_BASER_PHYADDR_SHIFT) & + R_GITS_BASER_PHYADDRH_64K_MASK) << + R_GITS_BASER_PHYADDRH_64K_SHIFT; + } + } + } else if (type == GITS_ITT_TYPE_COLLECTION) { + s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID); + + /* + * GITS_TYPER.HCC is 0 for this implementation + * hence writes are discarded if ct.valid is 0 + */ + if (s->ct.valid) { + s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); + s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); + + if (!s->ct.indirect) { + s->ct.max_entries = ((num_pages + 1) * page_sz) / + s->ct.entry_sz; + } else { + s->ct.max_entries = ((((num_pages + 1) * page_sz) / + L1TABLE_ENTRY_SIZE) * + (page_sz / s->ct.entry_sz)); + } + + if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) { + s->ct.max_collids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, + CIDBITS) + 1)); + } else { + /* 16-bit CollectionId supported when CIL == 0 */ + s->ct.max_collids = (1UL << 16); + } + + if ((page_sz == GITS_ITT_PAGE_SIZE_0) || + (page_sz == GITS_ITT_PAGE_SIZE_1)) { + s->ct.base_addr = FIELD_EX64(value, GITS_BASER, PHYADDR); + s->ct.base_addr <<= R_GITS_BASER_PHYADDR_SHIFT; + } else if (page_sz == GITS_ITT_PAGE_SIZE_2) { + s->ct.base_addr = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << + R_GITS_BASER_PHYADDRL_64K_SHIFT; + s->ct.base_addr |= ((value >> R_GITS_BASER_PHYADDR_SHIFT) & + R_GITS_BASER_PHYADDRH_64K_MASK) << + R_GITS_BASER_PHYADDRH_64K_SHIFT; + } + } + } else { + /* unsupported ITS table type */ + qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported ITS table type %d", + __func__, type); + return false; + } + return true; +} + +static bool extract_cmdq_params(GICv3ITSState *s) +{ + uint16_t num_pages = 0; + uint64_t value = s->cbaser; + + num_pages = FIELD_EX64(value, GITS_CBASER, SIZE); + + s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID); + + if (!num_pages || !s->cq.valid) { + return false; + } + + if (s->cq.valid) { + s->cq.max_entries = ((num_pages + 1) * GITS_ITT_PAGE_SIZE_0) / + GITS_CMDQ_ENTRY_SIZE; + s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR); + s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT; + } + return true; +} + static MemTxResult its_trans_writew(GICv3ITSState *s, hwaddr offset, uint64_t value, MemTxAttrs attrs) { @@ -126,7 +251,75 @@ static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset, uint64_t value, MemTxAttrs attrs) { MemTxResult result = MEMTX_OK; + int index; + uint64_t temp = 0; + switch (offset) { + case GITS_CTLR: + s->ctlr |= (value & ~(s->ctlr)); + break; + case GITS_CBASER: + /* GITS_CBASER register becomes RO if ITS is already enabled */ + if (!(s->ctlr & ITS_CTLR_ENABLED)) { + s->cbaser = deposit64(s->cbaser, 0, 32, value); + s->creadr = 0; + } + break; + case GITS_CBASER + 4: + /* GITS_CBASER register becomes RO if ITS is already enabled */ + if (!(s->ctlr & ITS_CTLR_ENABLED)) { + s->cbaser = deposit64(s->cbaser, 32, 32, value); + if (!extract_cmdq_params(s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: error extracting GITS_CBASER parameters " + TARGET_FMT_plx "\n", __func__, offset); + s->cbaser = 0; + result = MEMTX_ERROR; + } else { + s->creadr = 0; + } + } + break; + case GITS_CWRITER: + s->cwriter = deposit64(s->cwriter, 0, 32, value); + break; + case GITS_CWRITER + 4: + s->cwriter = deposit64(s->cwriter, 32, 32, value); + break; + case GITS_BASER ... GITS_BASER + 0x3f: + /* GITS_BASERn registers become RO if ITS is already enabled */ + if (!(s->ctlr & ITS_CTLR_ENABLED)) { + index = (offset - GITS_BASER) / 8; + + if (offset & 7) { + temp = s->baser[index]; + temp = deposit64(temp, 32, 32, (value & ~GITS_BASER_VAL_MASK)); + s->baser[index] |= temp; + + if (!extract_table_params(s, index)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: error extracting GITS_BASER parameters " + TARGET_FMT_plx "\n", __func__, offset); + s->baser[index] = 0; + result = MEMTX_ERROR; + } + } else { + s->baser[index] = deposit64(s->baser[index], 0, 32, value); + } + } + break; + case GITS_IIDR: + case GITS_TYPER: + case GITS_CREADR: + /* RO registers, ignore the write */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write to RO register at offset " + TARGET_FMT_plx "\n", __func__, offset); + break; + default: + result = MEMTX_ERROR; + break; + } return result; } @@ -134,7 +327,54 @@ static MemTxResult its_readl(GICv3ITSState *s, hwaddr offset, uint64_t *data, MemTxAttrs attrs) { MemTxResult result = MEMTX_OK; + int index; + switch (offset) { + case GITS_CTLR: + *data = s->ctlr; + break; + case GITS_IIDR: + *data = s->iidr; + break; + case GITS_PIDR2: + *data = 0x30; /* GICv3 */ + break; + case GITS_TYPER: + *data = extract64(s->typer, 0, 32); + break; + case GITS_TYPER + 4: + *data = extract64(s->typer, 32, 32); + break; + case GITS_CBASER: + *data = extract64(s->cbaser, 0, 32); + break; + case GITS_CBASER + 4: + *data = extract64(s->cbaser, 32, 32); + break; + case GITS_CREADR: + *data = extract64(s->creadr, 0, 32); + break; + case GITS_CREADR + 4: + *data = extract64(s->creadr, 32, 32); + break; + case GITS_CWRITER: + *data = extract64(s->cwriter, 0, 32); + break; + case GITS_CWRITER + 4: + *data = extract64(s->cwriter, 32, 32); + break; + case GITS_BASER ... GITS_BASER + 0x3f: + index = (offset - GITS_BASER) / 8; + if (offset & 7) { + *data = s->baser[index] >> 32; + } else { + *data = (uint32_t)s->baser[index]; + } + break; + default: + result = MEMTX_ERROR; + break; + } return result; } @@ -142,7 +382,52 @@ static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset, uint64_t value, MemTxAttrs attrs) { MemTxResult result = MEMTX_OK; + int index; + switch (offset) { + case GITS_BASER ... GITS_BASER + 0x3f: + /* GITS_BASERn registers become RO if ITS is already enabled */ + if (!(s->ctlr & ITS_CTLR_ENABLED)) { + index = (offset - GITS_BASER) / 8; + s->baser[index] |= (value & ~GITS_BASER_VAL_MASK); + if (!extract_table_params(s, index)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: error extracting GITS_BASER parameters " + TARGET_FMT_plx "\n", __func__, offset); + s->baser[index] = 0; + result = MEMTX_ERROR; + } + } + break; + case GITS_CBASER: + /* GITS_CBASER register becomes RO if ITS is already enabled */ + if (!(s->ctlr & ITS_CTLR_ENABLED)) { + s->cbaser = value; + if (!extract_cmdq_params(s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: error extracting GITS_CBASER parameters " + TARGET_FMT_plx "\n", __func__, offset); + s->cbaser = 0; + result = MEMTX_ERROR; + } else { + s->creadr = 0; + } + } + break; + case GITS_CWRITER: + s->cwriter = value; + break; + case GITS_TYPER: + case GITS_CREADR: + /* RO register, ignore the write */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write to RO register at offset " + TARGET_FMT_plx "\n", __func__, offset); + break; + default: + result = MEMTX_ERROR; + break; + } return result; } @@ -150,7 +435,29 @@ static MemTxResult its_readll(GICv3ITSState *s, hwaddr offset, uint64_t *data, MemTxAttrs attrs) { MemTxResult result = MEMTX_OK; + int index; + switch (offset) { + case GITS_TYPER: + *data = s->typer; + break; + case GITS_BASER ... GITS_BASER + 0x3f: + index = (offset - GITS_BASER) / 8; + *data = s->baser[index]; + break; + case GITS_CBASER: + *data = s->cbaser; + break; + case GITS_CREADR: + *data = s->creadr; + break; + case GITS_CWRITER: + *data = s->cwriter; + break; + default: + result = MEMTX_ERROR; + break; + } return result; } @@ -250,6 +557,9 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp) GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev); gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops); + + address_space_init(&s->gicv3->sysmem_as, s->gicv3->sysmem, + "gicv3-its-sysmem"); } static void gicv3_its_reset(DeviceState *dev) @@ -259,6 +569,9 @@ static void gicv3_its_reset(DeviceState *dev) if (s->gicv3->cpu->gicr_typer & GICR_TYPER_PLPIS) { c->parent_reset(dev); + memset(&s->dt, 0, sizeof(s->dt)); + memset(&s->ct, 0, sizeof(s->ct)); + memset(&s->cq, 0, sizeof(s->cq)); /* set the ITS default features supported */ s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c index 80cc9ec6d8..9c5c71f350 100644 --- a/hw/intc/arm_gicv3_its_common.c +++ b/hw/intc/arm_gicv3_its_common.c @@ -48,6 +48,42 @@ static int gicv3_its_post_load(void *opaque, int version_id) return 0; } +static const VMStateDescription vmstate_its_dtdesc = { + .name = "arm_gicv3_its_dtdesc", + .fields = (VMStateField[]) { + VMSTATE_BOOL(valid, DevTableDesc), + VMSTATE_BOOL(indirect, DevTableDesc), + VMSTATE_UINT16(entry_sz, DevTableDesc), + VMSTATE_UINT32(max_entries, DevTableDesc), + VMSTATE_UINT32(max_devids, DevTableDesc), + VMSTATE_UINT64(base_addr, DevTableDesc), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_its_ctdesc = { + .name = "arm_gicv3_its_ctdesc", + .fields = (VMStateField[]) { + VMSTATE_BOOL(valid, CollTableDesc), + VMSTATE_BOOL(indirect, CollTableDesc), + VMSTATE_UINT16(entry_sz, CollTableDesc), + VMSTATE_UINT32(max_entries, CollTableDesc), + VMSTATE_UINT32(max_collids, CollTableDesc), + VMSTATE_UINT64(base_addr, CollTableDesc), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_its_cqdesc = { + .name = "arm_gicv3_its_cqdesc", + .fields = (VMStateField[]) { + VMSTATE_BOOL(valid, CmdQDesc), + VMSTATE_UINT32(max_entries, CmdQDesc), + VMSTATE_UINT64(base_addr, CmdQDesc), + VMSTATE_END_OF_LIST(), + }, +}; + static const VMStateDescription vmstate_its = { .name = "arm_gicv3_its", .version_id = 1, @@ -56,6 +92,12 @@ static const VMStateDescription vmstate_its = { .post_load = gicv3_its_post_load, .priority = MIG_PRI_GICV3_ITS, .fields = (VMStateField[]) { + VMSTATE_STRUCT(dt, GICv3ITSState, 0, vmstate_its_dtdesc, + DevTableDesc), + VMSTATE_STRUCT(ct, GICv3ITSState, 0, vmstate_its_ctdesc, + CollTableDesc), + VMSTATE_STRUCT(cq, GICv3ITSState, 0, vmstate_its_cqdesc, + CmdQDesc), VMSTATE_UINT32(ctlr, GICv3ITSState), VMSTATE_UINT32(translater, GICv3ITSState), VMSTATE_UINT32(iidr, GICv3ITSState), diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 96cfe2dff9..b7701e8ca5 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -246,13 +246,14 @@ FIELD(GITS_BASER, INNERCACHE, 59, 3) FIELD(GITS_BASER, INDIRECT, 62, 1) FIELD(GITS_BASER, VALID, 63, 1) -#define GITS_BASER_PAGESIZE_4K 0 -#define GITS_BASER_PAGESIZE_16K 1 -#define GITS_BASER_PAGESIZE_64K 2 - -#define GITS_ITT_TYPE_DEVICE 1ULL -#define GITS_ITT_TYPE_COLLECTION 4ULL +FIELD(GITS_CBASER, SIZE, 0, 8) +FIELD(GITS_CBASER, SHAREABILITY, 10, 2) +FIELD(GITS_CBASER, PHYADDR, 12, 40) +FIELD(GITS_CBASER, OUTERCACHE, 53, 3) +FIELD(GITS_CBASER, INNERCACHE, 59, 3) +FIELD(GITS_CBASER, VALID, 63, 1) +FIELD(GITS_CTLR, ENABLED, 0, 1) FIELD(GITS_CTLR, QUIESCENT, 31, 1) FIELD(GITS_TYPER, PHYSICAL, 0, 1) @@ -264,6 +265,26 @@ FIELD(GITS_TYPER, PTA, 19, 1) FIELD(GITS_TYPER, CIDBITS, 32, 4) FIELD(GITS_TYPER, CIL, 36, 1) +#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */ + +#define GITS_BASER_VAL_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \ + R_GITS_BASER_TYPE_MASK) + +#define GITS_BASER_PAGESIZE_4K 0 +#define GITS_BASER_PAGESIZE_16K 1 +#define GITS_BASER_PAGESIZE_64K 2 + +#define GITS_ITT_TYPE_DEVICE 1ULL +#define GITS_ITT_TYPE_COLLECTION 4ULL + +#define GITS_ITT_PAGE_SIZE_0 0x1000 +#define GITS_ITT_PAGE_SIZE_1 0x4000 +#define GITS_ITT_PAGE_SIZE_2 0x10000 + +#define L1TABLE_ENTRY_SIZE 8 + +#define GITS_CMDQ_ENTRY_SIZE 32 + /** * Default features advertised by this version of ITS */ diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 91491a2f66..b0f2414fa3 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -226,12 +226,16 @@ struct GICv3State { int dev_fd; /* kvm device fd if backed by kvm vgic support */ Error *migration_blocker; + MemoryRegion *sysmem; + AddressSpace sysmem_as; + /* Distributor */ /* for a GIC with the security extensions the NS banked version of this * register is just an alias of bit 1 of the S banked version. */ uint32_t gicd_ctlr; + uint32_t gicd_typer; uint32_t gicd_statusr[2]; GIC_DECLARE_BITMAP(group); /* GICD_IGROUPR */ GIC_DECLARE_BITMAP(grpmod); /* GICD_IGRPMODR */ diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 08bc5652ed..b7eca57221 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -43,6 +43,30 @@ #define GITS_PIDR2 0xFFE8 +typedef struct { + bool valid; + bool indirect; + uint16_t entry_sz; + uint32_t max_entries; + uint32_t max_devids; + uint64_t base_addr; +} DevTableDesc; + +typedef struct { + bool valid; + bool indirect; + uint16_t entry_sz; + uint32_t max_entries; + uint32_t max_collids; + uint64_t base_addr; +} CollTableDesc; + +typedef struct { + bool valid; + uint32_t max_entries; + uint64_t base_addr; +} CmdQDesc; + struct GICv3ITSState { SysBusDevice parent_obj; @@ -66,6 +90,10 @@ struct GICv3ITSState { uint64_t creadr; uint64_t baser[8]; + DevTableDesc dt; + CollTableDesc ct; + CmdQDesc cq; + Error *migration_blocker; }; From patchwork Thu Apr 1 02:41:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176967 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCD68C433ED for ; Thu, 1 Apr 2021 02:45:26 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7016561059 for ; Thu, 1 Apr 2021 02:45:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7016561059 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49522 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnKn-0006qj-JT for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:45:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58364) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHU-0002fW-QB for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:00 -0400 Received: from mail-qk1-x72f.google.com ([2607:f8b0:4864:20::72f]:34308) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHR-00038p-M5 for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:00 -0400 Received: by mail-qk1-x72f.google.com with SMTP id g20so933764qkk.1 for ; Wed, 31 Mar 2021 19:41:57 -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 :mime-version:content-transfer-encoding; bh=+kLngbFEr9GhCFoyvPAOLu0rbvy+LRo3Rc7TDtcOjkI=; b=GpT8vs9YkGTOLq1hvyEw4lJRI5K5o8MwmvkpOjXFmJEdI3xY7i475iHBAUXBkTA2we 7j7yICUWDxl3D+kmtTtzOqTJkn8I9cL89VCN1+Z0DpF/umcnp9fEbQxIEtna4eANvTd2 g7Y3aaiv1Yd0wSoQUFK0E30V1LMBQJLQkGVaptcswmLeluv59VOrLwYOzuLAK622/rmD jz0ijvuBqjXNUs7G/gzByeIMp+bi2MTUg+0oKPVrljCD8/5L0olwdyRH/SdtNSzADYJX pvEWOzTpBaHLHZtkjuNtMn4vWTKiVjqBbmjVq7cemLvPqp1HJG36M4M7tJBYjnPsMm9L N3nw== 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:mime-version:content-transfer-encoding; bh=+kLngbFEr9GhCFoyvPAOLu0rbvy+LRo3Rc7TDtcOjkI=; b=b2deXo69qLJs8s0babZHKTzTz/ctogMOcd4ban+PSkKE1KxbWqAOgd0zpFvhHbMYhV tySDADRBIk3CvtdUq0ZyExnm56nSFGWHo3DfYrSgAOEs3RE6oPwVDGCKRGvB37rYHe/0 njDBZOmPQbnUncp3KHvPjoluwIyhV92KTsFFs5hS9Lum5k0OE8GgZ026GUD9zwXiI5Dp guQRWU8m442lA8md38ly4+bEDDEztz16pys6I7feaENMGiPYlfYcrB9lNit0BveV++TU 99QK1b1k1RvrcqKg5OCn0TNdlU3WS+mVUTZaJTklHWYljkpwsR9rnoBAceJL1OXkFJx5 Q97Q== X-Gm-Message-State: AOAM533mPzA2FC4AfITjSdQ1Cqk3PdCV2nfClvIG5WmXJqiSnmTvOP2d pIN/7YQ0nfq50z5SHNaJz+Bk2A== X-Google-Smtp-Source: ABdhPJywb7A8xShRiIUpL3QK8WmG2Eb1tdaL/AH3g2KgRMMaP7OoBQ82tf7dp5Hxc2R4OwBhLFfREg== X-Received: by 2002:a05:620a:e16:: with SMTP id y22mr6452628qkm.310.1617244916593; Wed, 31 Mar 2021 19:41:56 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:56 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 3/8] hw/intc: GICv3 ITS command queue framework Date: Wed, 31 Mar 2021 22:41:47 -0400 Message-Id: <20210401024152.203896-4-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::72f; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x72f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Added functionality to trigger ITS command queue processing on write to CWRITE register and process each command queue entry to identify the command type and handle commands like MAPD,MAPC,SYNC. Signed-off-by: Shashi Mallela --- hw/intc/arm_gicv3_its.c | 347 +++++++++++++++++++++++++++++++++++++++ hw/intc/gicv3_internal.h | 41 +++++ 2 files changed, 388 insertions(+) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 81373f049d..fcac33c836 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -28,6 +28,347 @@ struct GICv3ITSClass { void (*parent_reset)(DeviceState *dev); }; +static MemTxResult process_sync(GICv3ITSState *s, uint32_t offset) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint64_t rdbase; + uint64_t value; + bool pta = false; + MemTxResult res = MEMTX_OK; + + offset += NUM_BYTES_IN_DW; + offset += NUM_BYTES_IN_DW; + + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + + if (FIELD_EX64(s->typer, GITS_TYPER, PTA)) { + /* + * only bits[47:16] are considered instead of bits [51:16] + * since with a physical address the target address must be + * 64KB aligned + */ + rdbase = (value >> RDBASE_OFFSET) & RDBASE_MASK; + pta = true; + } else { + rdbase = (value >> RDBASE_OFFSET) & RDBASE_PROCNUM_MASK; + } + + if (!pta && (rdbase < (s->gicv3->num_cpu))) { + /* + * Current implementation makes a blocking synchronous call + * for every command issued earlier,hence the internal state + * is already consistent by the time SYNC command is executed. + */ + } + + offset += NUM_BYTES_IN_DW; + return res; +} + +static void update_cte(GICv3ITSState *s, uint16_t icid, uint64_t cte) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint64_t value; + uint8_t page_sz_type; + uint64_t l2t_addr; + bool valid_l2t; + uint32_t l2t_id; + uint32_t page_sz = 0; + uint32_t max_l2_entries; + + if (s->ct.indirect) { + /* 2 level table */ + page_sz_type = FIELD_EX64(s->baser[1], GITS_BASER, PAGESIZE); + + if (page_sz_type == 0) { + page_sz = GITS_ITT_PAGE_SIZE_0; + } else if (page_sz_type == 1) { + page_sz = GITS_ITT_PAGE_SIZE_1; + } else if (page_sz_type == 2) { + page_sz = GITS_ITT_PAGE_SIZE_2; + } + + l2t_id = icid / (page_sz / L1TABLE_ENTRY_SIZE); + + value = address_space_ldq_le(as, + s->ct.base_addr + + (l2t_id * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, NULL); + + valid_l2t = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid_l2t) { + max_l2_entries = page_sz / s->ct.entry_sz; + + l2t_addr = (value >> page_sz_type) & + ((1ULL << (51 - page_sz_type)) - 1); + + address_space_write(as, l2t_addr + + ((icid % max_l2_entries) * GITS_CTE_SIZE), + MEMTXATTRS_UNSPECIFIED, + &cte, sizeof(cte)); + } + } else { + /* Flat level table */ + address_space_write(as, s->ct.base_addr + (icid * GITS_CTE_SIZE), + MEMTXATTRS_UNSPECIFIED, &cte, + sizeof(cte)); + } +} + +static MemTxResult process_mapc(GICv3ITSState *s, uint32_t offset) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint16_t icid; + uint64_t rdbase; + bool valid; + bool pta = false; + MemTxResult res = MEMTX_OK; + uint64_t cte_entry; + uint64_t value; + + offset += NUM_BYTES_IN_DW; + offset += NUM_BYTES_IN_DW; + + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + + icid = value & ICID_MASK; + + if (FIELD_EX64(s->typer, GITS_TYPER, PTA)) { + /* + * only bits[47:16] are considered instead of bits [51:16] + * since with a physical address the target address must be + * 64KB aligned + */ + rdbase = (value >> RDBASE_OFFSET) & RDBASE_MASK; + pta = true; + } else { + rdbase = (value >> RDBASE_OFFSET) & RDBASE_PROCNUM_MASK; + } + + valid = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid) { + if ((icid > s->ct.max_collids) || (!pta && + (rdbase > s->gicv3->num_cpu))) { + if (FIELD_EX64(s->typer, GITS_TYPER, SEIS)) { + /* Generate System Error here if supported */ + } + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid collection table attributes " + "icid %d rdbase %lu\n", __func__, icid, rdbase); + /* + * in this implementation,in case of error + * we ignore this command and move onto the next + * command in the queue + */ + } else { + if (s->ct.valid) { + /* add mapping entry to collection table */ + cte_entry = (valid & VALID_MASK) | + (pta ? ((rdbase & RDBASE_MASK) << 1ULL) : + ((rdbase & RDBASE_PROCNUM_MASK) << 1ULL)); + + update_cte(s, icid, cte_entry); + } + } + } else { + if (s->ct.valid) { + /* remove mapping entry from collection table */ + cte_entry = 0; + + update_cte(s, icid, cte_entry); + } + } + + offset += NUM_BYTES_IN_DW; + offset += NUM_BYTES_IN_DW; + + return res; +} + +static void update_dte(GICv3ITSState *s, uint32_t devid, uint64_t dte) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint64_t value; + uint8_t page_sz_type; + uint64_t l2t_addr; + bool valid_l2t; + uint32_t l2t_id; + uint32_t page_sz = 0; + uint32_t max_l2_entries; + + if (s->dt.indirect) { + /* 2 level table */ + page_sz_type = FIELD_EX64(s->baser[0], GITS_BASER, PAGESIZE); + + if (page_sz_type == 0) { + page_sz = GITS_ITT_PAGE_SIZE_0; + } else if (page_sz_type == 1) { + page_sz = GITS_ITT_PAGE_SIZE_1; + } else if (page_sz_type == 2) { + page_sz = GITS_ITT_PAGE_SIZE_2; + } + + l2t_id = devid / (page_sz / L1TABLE_ENTRY_SIZE); + + value = address_space_ldq_le(as, + s->dt.base_addr + + (l2t_id * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, NULL); + + valid_l2t = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid_l2t) { + max_l2_entries = page_sz / s->dt.entry_sz; + + l2t_addr = (value >> page_sz_type) & + ((1ULL << (51 - page_sz_type)) - 1); + + address_space_write(as, l2t_addr + + ((devid % max_l2_entries) * GITS_DTE_SIZE), + MEMTXATTRS_UNSPECIFIED, &dte, sizeof(dte)); + } + } else { + /* Flat level table */ + address_space_write(as, s->dt.base_addr + (devid * GITS_DTE_SIZE), + MEMTXATTRS_UNSPECIFIED, &dte, sizeof(dte)); + } +} + +static MemTxResult process_mapd(GICv3ITSState *s, uint64_t value, + uint32_t offset) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint32_t devid; + uint8_t size; + uint64_t itt_addr; + bool valid; + MemTxResult res = MEMTX_OK; + uint64_t dte_entry = 0; + + devid = (value >> DEVID_OFFSET) & DEVID_MASK; + + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + size = (value & SIZE_MASK); + + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + itt_addr = (value >> ITTADDR_OFFSET) & ITTADDR_MASK; + + valid = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid) { + if ((devid > s->dt.max_devids) || + (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { + if (FIELD_EX64(s->typer, GITS_TYPER, SEIS)) { + /* Generate System Error here if supported */ + } + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid device table attributes " + "devid %d or size %d\n", __func__, devid, size); + /* + * in this implementation,in case of error + * we ignore this command and move onto the next + * command in the queue + */ + } else { + if (s->dt.valid) { + /* add mapping entry to device table */ + dte_entry = (valid & VALID_MASK) | + ((size & SIZE_MASK) << 1U) | + ((itt_addr & ITTADDR_MASK) << 6ULL); + + update_dte(s, devid, dte_entry); + } + } + } else { + if (s->dt.valid) { + /* remove mapping entry from device table */ + dte_entry = 0; + update_dte(s, devid, dte_entry); + } + } + + offset += NUM_BYTES_IN_DW; + offset += NUM_BYTES_IN_DW; + + return res; +} + +/* + * Current implementation blocks until all + * commands are processed + */ +static MemTxResult process_cmdq(GICv3ITSState *s) +{ + uint32_t wr_offset = 0; + uint32_t rd_offset = 0; + uint32_t cq_offset = 0; + uint64_t data; + AddressSpace *as = &s->gicv3->sysmem_as; + MemTxResult res = MEMTX_OK; + uint8_t cmd; + + wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET); + + if (wr_offset > s->cq.max_entries) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid write offset " + "%d\n", __func__, wr_offset); + res = MEMTX_ERROR; + return res; + } + + rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET); + + while (wr_offset != rd_offset) { + cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE); + data = address_space_ldq_le(as, s->cq.base_addr + cq_offset, + MEMTXATTRS_UNSPECIFIED, &res); + cmd = (data & CMD_MASK); + + switch (cmd) { + case GITS_CMD_INT: + break; + case GITS_CMD_CLEAR: + break; + case GITS_CMD_SYNC: + res = process_sync(s, cq_offset); + break; + case GITS_CMD_MAPD: + res = process_mapd(s, data, cq_offset); + break; + case GITS_CMD_MAPC: + res = process_mapc(s, cq_offset); + break; + case GITS_CMD_MAPTI: + break; + case GITS_CMD_MAPI: + break; + case GITS_CMD_DISCARD: + break; + default: + break; + } + if (res == MEMTX_OK) { + rd_offset++; + rd_offset %= s->cq.max_entries; + s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %x cmd processing failed!!\n", __func__, cmd); + break; + } + } + return res; +} + static bool extract_table_params(GICv3ITSState *s, int index) { uint16_t num_pages = 0; @@ -282,6 +623,9 @@ static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset, break; case GITS_CWRITER: s->cwriter = deposit64(s->cwriter, 0, 32, value); + if ((s->ctlr & ITS_CTLR_ENABLED) && (s->cwriter != s->creadr)) { + result = process_cmdq(s); + } break; case GITS_CWRITER + 4: s->cwriter = deposit64(s->cwriter, 32, 32, value); @@ -416,6 +760,9 @@ static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset, break; case GITS_CWRITER: s->cwriter = value; + if ((s->ctlr & ITS_CTLR_ENABLED) && (s->cwriter != s->creadr)) { + result = process_cmdq(s); + } break; case GITS_TYPER: case GITS_CREADR: diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index b7701e8ca5..7e1ff426ef 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -253,6 +253,12 @@ FIELD(GITS_CBASER, OUTERCACHE, 53, 3) FIELD(GITS_CBASER, INNERCACHE, 59, 3) FIELD(GITS_CBASER, VALID, 63, 1) +FIELD(GITS_CREADR, STALLED, 0, 1) +FIELD(GITS_CREADR, OFFSET, 5, 15) + +FIELD(GITS_CWRITER, RETRY, 0, 1) +FIELD(GITS_CWRITER, OFFSET, 5, 15) + FIELD(GITS_CTLR, ENABLED, 0, 1) FIELD(GITS_CTLR, QUIESCENT, 31, 1) @@ -284,6 +290,41 @@ FIELD(GITS_TYPER, CIL, 36, 1) #define L1TABLE_ENTRY_SIZE 8 #define GITS_CMDQ_ENTRY_SIZE 32 +#define NUM_BYTES_IN_DW 8 + +#define CMD_MASK 0xff + +/* ITS Commands */ +#define GITS_CMD_CLEAR 0x04 +#define GITS_CMD_DISCARD 0x0F +#define GITS_CMD_INT 0x03 +#define GITS_CMD_MAPC 0x09 +#define GITS_CMD_MAPD 0x08 +#define GITS_CMD_MAPI 0x0B +#define GITS_CMD_MAPTI 0x0A +#define GITS_CMD_SYNC 0x05 + +/* MAPC command fields */ +#define ICID_LEN 16 +#define ICID_MASK ((1U << ICID_LEN) - 1) +#define RDBASE_LEN 32 +#define RDBASE_OFFSET 16 +#define RDBASE_MASK ((1ULL << RDBASE_LEN) - 1) +#define RDBASE_PROCNUM_LEN 16 +#define RDBASE_PROCNUM_MASK ((1ULL << RDBASE_PROCNUM_LEN) - 1) + +#define DEVID_OFFSET 32 +#define DEVID_LEN 32 +#define DEVID_MASK ((1ULL << DEVID_LEN) - 1) + +/* MAPD command fields */ +#define ITTADDR_LEN 44 +#define ITTADDR_OFFSET 8 +#define ITTADDR_MASK ((1ULL << ITTADDR_LEN) - 1) +#define SIZE_MASK 0x1f + +#define VALID_SHIFT 63 +#define VALID_MASK 0x1 /** * Default features advertised by this version of ITS From patchwork Thu Apr 1 02:41:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176971 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60EB4C433B4 for ; Thu, 1 Apr 2021 02:46:29 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CC1C2608FE for ; Thu, 1 Apr 2021 02:46:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CC1C2608FE Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:52266 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnLn-000811-OX for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:46:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58432) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHX-0002mN-V1 for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:04 -0400 Received: from mail-qk1-x730.google.com ([2607:f8b0:4864:20::730]:45708) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHS-000396-CW for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:03 -0400 Received: by mail-qk1-x730.google.com with SMTP id q3so853617qkq.12 for ; Wed, 31 Mar 2021 19:41:57 -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 :mime-version:content-transfer-encoding; bh=oUllfF8CUAQznaw9J4vMHWhjv+WxmuQIU0bgqJF76zY=; b=JAi4JupszjmWh1D1Rzp6GObouhoWgs7RIYErycQqFmq4Y9h4Hmo3qekqFQb4HwfXk6 S5vdu24GwBQdB/mC1XowKvHCq8HZbD0NmhI5KEb+OnbBHJ7Utoay1C+Mb1dIrFd01qss 5TXPUR2m2ighSU/JRmagpPpFoiQSO07JUoMiIx/ITrZ+xBTzP/JCJZ8a2TH9RpWwHWX8 yUshldpLxw5zmUokFxTvbTO9UyGITtNV1P4B1aU5L414MIxWtcdZODyOPJHBmZy+/vgA ua5lNoL+zY9+MYJezf5mHapXXblgAFpeEPqcdSXSvbCTKGeiJAhS6H68qmzsQWAyAFUy LG3Q== 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:mime-version:content-transfer-encoding; bh=oUllfF8CUAQznaw9J4vMHWhjv+WxmuQIU0bgqJF76zY=; b=Ho4LfnkVNE+iVCtiCaHqoC/7gmJz9iLDwHsw15gW8rhM5awnizOK0cXDWZXO784zbw lMtunrUcofodx4XrCGDXgLeVFtTt0iMRH45H0aX+U8s8UV5VYVf2US0AWwe+NqkqUKt1 Dg52Y/NVj5D1s/uTRlyExSPaf+dgT1GdIzLpngD3hs9NtPulTKwtS7HQ+hGJzHh29iQT jhoXaqhqohcCjPVCfOeX36jiPSDTSJRi3h/z71fWnUiMRTyGdRq8rXePRmW16sgQWo7a em0vPTBc/t31/B+2hwW/yYT34zo28HibPRpgzJ1ccKvnKUZTq7WXaoJd9ZRtxSt/RVqp mfkQ== X-Gm-Message-State: AOAM532vJN49V2P8gCcqiKgwuU8THNSLWL94tjm1cX7+Ejid48qT7Y0M DOLFLNZa1XsXFpjxSNES032PzQ== X-Google-Smtp-Source: ABdhPJyRfcF0NOIxvGN2jRANCQK2my5b2euXylqpA4ExScuktE6TbqijmTzt3FJK9TEpfdvg3CtLMg== X-Received: by 2002:a37:7c8:: with SMTP id 191mr6274003qkh.53.1617244917260; Wed, 31 Mar 2021 19:41:57 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:57 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 4/8] hw/intc: GICv3 ITS Command processing Date: Wed, 31 Mar 2021 22:41:48 -0400 Message-Id: <20210401024152.203896-5-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::730; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x730.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Added ITS command queue handling for MAPTI,MAPI commands,handled ITS translation which triggers an LPI via INT command as well as write to GITS_TRANSLATER register,defined enum to differentiate between ITS command interrupt trigger and GITS_TRANSLATER based interrupt trigger. Each of these commands make use of other functionalities implemented to get device table entry,collection table entry or interrupt translation table entry required for their processing. Signed-off-by: Shashi Mallela --- hw/intc/arm_gicv3_its.c | 360 ++++++++++++++++++++++++++++- hw/intc/gicv3_internal.h | 7 + include/hw/intc/arm_gicv3_common.h | 2 + 3 files changed, 368 insertions(+), 1 deletion(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index fcac33c836..0e3f176809 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -28,6 +28,152 @@ struct GICv3ITSClass { void (*parent_reset)(DeviceState *dev); }; +typedef enum ItsCmdType { + NONE = 0, /* internal indication for GITS_TRANSLATER write */ + CLEAR = 1, + DISCARD = 2, + INT = 3, +} ItsCmdType; + +static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint8_t page_sz_type; + uint64_t l2t_addr; + uint64_t value; + bool valid_l2t; + uint32_t l2t_id; + uint32_t page_sz = 0; + uint32_t max_l2_entries; + bool status = false; + + if (s->ct.indirect) { + /* 2 level table */ + page_sz_type = FIELD_EX64(s->baser[1], GITS_BASER, PAGESIZE); + + if (page_sz_type == 0) { + page_sz = GITS_ITT_PAGE_SIZE_0; + } else if (page_sz_type == 1) { + page_sz = GITS_ITT_PAGE_SIZE_1; + } else if (page_sz_type == 2) { + page_sz = GITS_ITT_PAGE_SIZE_2; + } + + l2t_id = icid / (page_sz / L1TABLE_ENTRY_SIZE); + + value = address_space_ldq_le(as, + s->ct.base_addr + + (l2t_id * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, NULL); + + valid_l2t = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid_l2t) { + max_l2_entries = page_sz / s->ct.entry_sz; + + l2t_addr = (value >> page_sz_type) & + ((1ULL << (51 - page_sz_type)) - 1); + + address_space_read(as, l2t_addr + + ((icid % max_l2_entries) * GITS_CTE_SIZE), + MEMTXATTRS_UNSPECIFIED, + cte, sizeof(*cte)); + } + } else { + /* Flat level table */ + address_space_read(as, s->ct.base_addr + (icid * GITS_CTE_SIZE), + MEMTXATTRS_UNSPECIFIED, cte, + sizeof(*cte)); + } + + if (*cte & VALID_MASK) { + status = true; + } + + return status; +} + +static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, + uint16_t *icid, uint32_t *pIntid) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint8_t buff[ITS_ITT_ENTRY_SIZE]; + uint64_t itt_addr; + bool status = false; + + itt_addr = (dte >> 6ULL) & ITTADDR_MASK; + itt_addr <<= ITTADDR_OFFSET; /* 256 byte aligned */ + + address_space_read(as, itt_addr + (eventid * sizeof(buff)), + MEMTXATTRS_UNSPECIFIED, &buff, + sizeof(buff)); + + if (buff[0] & VALID_MASK) { + if ((buff[0] >> 1U) & GITS_TYPE_PHYSICAL) { + memcpy(pIntid, &buff[1], 3); + memcpy(icid, &buff[7], sizeof(*icid)); + status = true; + } + } + + return status; +} + +static uint64_t get_dte(GICv3ITSState *s, uint32_t devid) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint8_t page_sz_type; + uint64_t l2t_addr; + uint64_t value; + bool valid_l2t; + uint32_t l2t_id; + uint32_t page_sz = 0; + uint32_t max_l2_entries; + + if (s->dt.indirect) { + /* 2 level table */ + page_sz_type = FIELD_EX64(s->baser[0], GITS_BASER, PAGESIZE); + + if (page_sz_type == 0) { + page_sz = GITS_ITT_PAGE_SIZE_0; + } else if (page_sz_type == 1) { + page_sz = GITS_ITT_PAGE_SIZE_1; + } else if (page_sz_type == 2) { + page_sz = GITS_ITT_PAGE_SIZE_2; + } + + l2t_id = devid / (page_sz / L1TABLE_ENTRY_SIZE); + + value = address_space_ldq_le(as, + s->dt.base_addr + + (l2t_id * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, NULL); + + valid_l2t = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid_l2t) { + max_l2_entries = page_sz / s->dt.entry_sz; + + l2t_addr = (value >> page_sz_type) & + ((1ULL << (51 - page_sz_type)) - 1); + + value = 0; + address_space_read(as, l2t_addr + + ((devid % max_l2_entries) * GITS_DTE_SIZE), + MEMTXATTRS_UNSPECIFIED, + &value, sizeof(value)); + } + } else { + /* Flat level table */ + value = 0; + address_space_read(as, s->dt.base_addr + (devid * GITS_DTE_SIZE), + MEMTXATTRS_UNSPECIFIED, &value, + sizeof(value)); + } + + return value; +} + static MemTxResult process_sync(GICv3ITSState *s, uint32_t offset) { AddressSpace *as = &s->gicv3->sysmem_as; @@ -66,6 +212,187 @@ static MemTxResult process_sync(GICv3ITSState *s, uint32_t offset) return res; } +static MemTxResult process_int(GICv3ITSState *s, uint64_t value, + uint32_t offset, ItsCmdType cmd) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint32_t devid, eventid; + MemTxResult res = MEMTX_OK; + bool dte_valid; + uint64_t dte = 0; + uint32_t max_eventid; + uint16_t icid = 0; + uint32_t pIntid = 0; + bool ite_valid = false; + uint64_t cte = 0; + bool cte_valid = false; + uint8_t buff[ITS_ITT_ENTRY_SIZE]; + uint64_t itt_addr; + + if (cmd == NONE) { + devid = offset; + } else { + devid = (value >> DEVID_OFFSET) & DEVID_MASK; + + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + } + + eventid = (value & EVENTID_MASK); + + dte = get_dte(s, devid); + dte_valid = dte & VALID_MASK; + + if (dte_valid) { + max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); + + ite_valid = get_ite(s, eventid, dte, &icid, &pIntid); + + if (ite_valid) { + cte_valid = get_cte(s, icid, &cte); + } + } + + if ((devid > s->dt.max_devids) || !dte_valid || !ite_valid || + !cte_valid || (eventid > max_eventid)) { + if (FIELD_EX64(s->typer, GITS_TYPER, SEIS)) { + /* + * Generate System Error here if supported + * for each of the individual error cases + */ + } + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid interrupt translation table attributes " + "devid %d or eventid %d\n", + __func__, devid, eventid); + /* + * in this implementation,in case of error + * we ignore this command and move onto the next + * command in the queue + */ + } else { + if (FIELD_EX64(s->typer, GITS_TYPER, PTA)) { + /* + * only bits[47:16] are considered instead of bits [51:16] + * since with a physical address the target address must be + * 64KB aligned + */ + + /* + * Current implementation only supports rdbase == procnum + * Hence rdbase physical address is ignored + */ + } else { + + if (cmd == DISCARD) { + /* remove mapping from interrupt translation table */ + memset(buff, 0, sizeof(buff)); + + itt_addr = (dte >> 6ULL) & ITTADDR_MASK; + itt_addr <<= ITTADDR_OFFSET; /* 256 byte aligned */ + + address_space_write(as, itt_addr + (eventid * sizeof(buff)), + MEMTXATTRS_UNSPECIFIED, &buff, + sizeof(buff)); + } + } + } + + if (cmd != NONE) { + offset += NUM_BYTES_IN_DW; + offset += NUM_BYTES_IN_DW; + } + + return res; +} + +static MemTxResult process_mapti(GICv3ITSState *s, uint64_t value, + uint32_t offset, bool ignore_pInt) +{ + AddressSpace *as = &s->gicv3->sysmem_as; + uint32_t devid, eventid; + uint32_t pIntid = 0; + uint32_t max_eventid, max_Intid; + bool dte_valid; + MemTxResult res = MEMTX_OK; + uint16_t icid = 0; + uint64_t dte = 0; + uint64_t itt_addr; + uint8_t buff[ITS_ITT_ENTRY_SIZE]; + uint32_t int_spurious = INTID_SPURIOUS; + + devid = (value >> DEVID_OFFSET) & DEVID_MASK; + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + + eventid = (value & EVENTID_MASK); + + if (!ignore_pInt) { + pIntid = (value >> pINTID_OFFSET) & pINTID_MASK; + } + + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + + icid = value & ICID_MASK; + + dte = get_dte(s, devid); + dte_valid = dte & VALID_MASK; + + max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); + + if (!ignore_pInt) { + max_Intid = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, IDBITS) + 1)); + } + + if ((devid > s->dt.max_devids) || (icid > s->ct.max_collids) || + !dte_valid || (eventid > max_eventid) || + (!ignore_pInt && ((pIntid < GICV3_LPI_INTID_START) || + (pIntid > max_Intid)))) { + if (FIELD_EX64(s->typer, GITS_TYPER, SEIS)) { + /* + * Generate System Error here if supported + * for each of the individual error cases + */ + } + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid interrupt translation table attributes " + "devid %d or icid %d or eventid %d or pIntid %d\n", + __func__, devid, icid, eventid, pIntid); + /* + * in this implementation,in case of error + * we ignore this command and move onto the next + * command in the queue + */ + } else { + /* add entry to interrupt translation table */ + memset(buff, 0, sizeof(buff)); + buff[0] = (dte_valid & VALID_MASK) | (GITS_TYPE_PHYSICAL << 1U); + if (ignore_pInt) { + memcpy(&buff[1], &eventid, 3); + } else { + memcpy(&buff[1], &pIntid, 3); + } + memcpy(&buff[4], &int_spurious, 3); + memcpy(&buff[7], &icid, sizeof(icid)); + + itt_addr = (dte >> 6ULL) & ITTADDR_MASK; + itt_addr <<= ITTADDR_OFFSET; /* 256 byte aligned */ + + address_space_write(as, itt_addr + (eventid * sizeof(buff)), + MEMTXATTRS_UNSPECIFIED, &buff, + sizeof(buff)); + } + + offset += NUM_BYTES_IN_DW; + offset += NUM_BYTES_IN_DW; + + return res; +} + static void update_cte(GICv3ITSState *s, uint16_t icid, uint64_t cte) { AddressSpace *as = &s->gicv3->sysmem_as; @@ -239,7 +566,7 @@ static void update_dte(GICv3ITSState *s, uint32_t devid, uint64_t dte) } static MemTxResult process_mapd(GICv3ITSState *s, uint64_t value, - uint32_t offset) + uint32_t offset) { AddressSpace *as = &s->gicv3->sysmem_as; uint32_t devid; @@ -335,8 +662,10 @@ static MemTxResult process_cmdq(GICv3ITSState *s) switch (cmd) { case GITS_CMD_INT: + res = process_int(s, data, cq_offset, INT); break; case GITS_CMD_CLEAR: + res = process_int(s, data, cq_offset, CLEAR); break; case GITS_CMD_SYNC: res = process_sync(s, cq_offset); @@ -348,10 +677,13 @@ static MemTxResult process_cmdq(GICv3ITSState *s) res = process_mapc(s, cq_offset); break; case GITS_CMD_MAPTI: + res = process_mapti(s, data, cq_offset, false); break; case GITS_CMD_MAPI: + res = process_mapti(s, data, cq_offset, true); break; case GITS_CMD_DISCARD: + res = process_int(s, data, cq_offset, DISCARD); break; default: break; @@ -498,7 +830,20 @@ static MemTxResult its_trans_writew(GICv3ITSState *s, hwaddr offset, uint64_t value, MemTxAttrs attrs) { MemTxResult result = MEMTX_OK; + uint32_t devid = 0; + switch (offset) { + case GITS_TRANSLATER: + if (s->ctlr & ITS_CTLR_ENABLED) { + s->translater = (value & 0x0000FFFFU); + devid = attrs.requester_id; + result = process_int(s, s->translater, devid, NONE); + } + break; + default: + result = MEMTX_ERROR; + break; + } return result; } @@ -506,7 +851,20 @@ static MemTxResult its_trans_writel(GICv3ITSState *s, hwaddr offset, uint64_t value, MemTxAttrs attrs) { MemTxResult result = MEMTX_OK; + uint32_t devid = 0; + switch (offset) { + case GITS_TRANSLATER: + if (s->ctlr & ITS_CTLR_ENABLED) { + s->translater = value; + devid = attrs.requester_id; + result = process_int(s, s->translater, devid, NONE); + } + break; + default: + result = MEMTX_ERROR; + break; + } return result; } diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 7e1ff426ef..e9f9aa6722 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -323,6 +323,13 @@ FIELD(GITS_TYPER, CIL, 36, 1) #define ITTADDR_MASK ((1ULL << ITTADDR_LEN) - 1) #define SIZE_MASK 0x1f +/* MAPI command fields */ +#define EVENTID_MASK ((1ULL << 32) - 1) + +/* MAPTI command fields */ +#define pINTID_OFFSET 32 +#define pINTID_MASK ((1ULL << 32) - 1) + #define VALID_SHIFT 63 #define VALID_MASK 0x1 diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index b0f2414fa3..3a710592a9 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -36,6 +36,8 @@ #define GICV3_MAXIRQ 1020 #define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL) +#define GICV3_LPI_INTID_START 8192 + #define GICV3_REDIST_SIZE 0x20000 /* Number of SGI target-list bits */ From patchwork Thu Apr 1 02:41:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176975 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 243A9C433B4 for ; Thu, 1 Apr 2021 02:48:23 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A485E6008E for ; Thu, 1 Apr 2021 02:48:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A485E6008E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:57728 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnNd-0001mb-Ky for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:48:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58434) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHY-0002mw-5d for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:04 -0400 Received: from mail-qk1-x732.google.com ([2607:f8b0:4864:20::732]:34311) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHS-0003AL-UE for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:03 -0400 Received: by mail-qk1-x732.google.com with SMTP id g20so933801qkk.1 for ; Wed, 31 Mar 2021 19:41:58 -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 :mime-version:content-transfer-encoding; bh=kpspPHcJfg6Gs/nyqw3eZ3/iN7HLzESlLVAgrEAXZC0=; b=pSlqlLyrw7BbRzBQBbDAlHy1NNraaTTJah96AyNOajiF4GgtFeYqHS8fSMZULbxSJJ dhQJXNUu6IcWXRt2gGQpW3K1Xms3qvc+J7/NDLIwZZDp8djBNcMpfeuWn5OAtVUZzJmB ZUASqAQ19EsZG+yQkKgUBUjm0Upj/UVZusu7zL8gsSQs2d5msnGtkaB5/sKPoGlchtVN mH9pCgYxaHBbi2ZsOTAZlkvBhb2Av4PjkHeQh0l+6sx/Hj+dB6yz3rAGhn79rQoakj1B RO+tPiHpIceXN4l1P2bE9PatSImsrAH8lsFVSiHUcIwO7NAPziplb1XfkZfvcmFtffvJ 2IMQ== 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:mime-version:content-transfer-encoding; bh=kpspPHcJfg6Gs/nyqw3eZ3/iN7HLzESlLVAgrEAXZC0=; b=jn336H9pdzxHV0QCayhLMrHMQGcTk+VRWbBebc4+Ou+6uUZu3GynM3jL+ntyxUbR6e DqCtboaPIkTEd2AfVEnTWeCOrv6CQx2+CPttGlMWSHNktbBaHXzh0ZlF+m3ci1zP1djm 47zoRlMst42FjtIG0q9TG4n6doGJeZ6eO30vOWcwip9v73zl2TaWjfVx5WX57vY2xD0n sZ6R6n3q09pyNU3Q2Y/8sUGDC93rXeblldubK7Am0XDgNBFZXHEkRbDyzZa3/MhGFyob krQyw9ipFWAmpA7j50RqSTlEZ5oi1rKTbn8E7NbvAcZbUolEv5etK3Aau8JEYWEPRp+q +c/g== X-Gm-Message-State: AOAM532wr2BJ66ORQd5AySQi1Dwhw5u/ncAWysXzR9/IAYUNHRmkhM9B jCs0uqdvEZdTcln21BfEC+kgzQ== X-Google-Smtp-Source: ABdhPJyMmT/oE/xcZkqGW05oi7zHEf7MFN/HtPzx5kA7H0vsplMnyLfCk6urns2HVlpltgFbQl0hrA== X-Received: by 2002:a37:a008:: with SMTP id j8mr6176955qke.343.1617244917890; Wed, 31 Mar 2021 19:41:57 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:57 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 5/8] hw/intc: GICv3 ITS Feature enablement Date: Wed, 31 Mar 2021 22:41:49 -0400 Message-Id: <20210401024152.203896-6-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::732; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x732.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Added properties to enable ITS feature and define qemu system address space memory in gicv3 common,setup distributor and redistributor registers to indicate LPI support. Signed-off-by: Shashi Mallela --- hw/intc/arm_gicv3_common.c | 16 ++++++++++++++++ hw/intc/arm_gicv3_dist.c | 22 ++++++++++++++++++++-- hw/intc/arm_gicv3_redist.c | 28 +++++++++++++++++++++++++--- hw/intc/gicv3_internal.h | 17 +++++++++++++++++ include/hw/intc/arm_gicv3_common.h | 8 ++++++++ 5 files changed, 86 insertions(+), 5 deletions(-) diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c index 58ef65f589..3bfc52f7fa 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c @@ -156,6 +156,7 @@ static const VMStateDescription vmstate_gicv3_cpu = { VMSTATE_UINT32(gicr_waker, GICv3CPUState), VMSTATE_UINT64(gicr_propbaser, GICv3CPUState), VMSTATE_UINT64(gicr_pendbaser, GICv3CPUState), + VMSTATE_BOOL(lpi_outofrange, GICv3CPUState), VMSTATE_UINT32(gicr_igroupr0, GICv3CPUState), VMSTATE_UINT32(gicr_ienabler0, GICv3CPUState), VMSTATE_UINT32(gicr_ipendr0, GICv3CPUState), @@ -227,6 +228,7 @@ static const VMStateDescription vmstate_gicv3 = { .priority = MIG_PRI_GICV3, .fields = (VMStateField[]) { VMSTATE_UINT32(gicd_ctlr, GICv3State), + VMSTATE_UINT32(gicd_typer, GICv3State), VMSTATE_UINT32_ARRAY(gicd_statusr, GICv3State, 2), VMSTATE_UINT32_ARRAY(group, GICv3State, GICV3_BMP_SIZE), VMSTATE_UINT32_ARRAY(grpmod, GICv3State, GICV3_BMP_SIZE), @@ -381,6 +383,16 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) (1 << 24) | (i << 8) | (last << 4); + + if (s->lpi_enable) { + s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS; + + if (!s->sysmem) { + error_setg(errp, + "Redist-ITS: Guest 'sysmem' reference link not set"); + return; + } + } } } @@ -406,6 +418,7 @@ static void arm_gicv3_common_reset(DeviceState *dev) cs->gicr_waker = GICR_WAKER_ProcessorSleep | GICR_WAKER_ChildrenAsleep; cs->gicr_propbaser = 0; cs->gicr_pendbaser = 0; + cs->lpi_outofrange = false; /* If we're resetting a TZ-aware GIC as if secure firmware * had set it up ready to start a kernel in non-secure, we * need to set interrupts to group 1 so the kernel can use them. @@ -494,9 +507,12 @@ static Property arm_gicv3_common_properties[] = { DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1), DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32), DEFINE_PROP_UINT32("revision", GICv3State, revision, 3), + DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0), DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0), DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions, redist_region_count, qdev_prop_uint32, uint32_t), + DEFINE_PROP_LINK("sysmem", GICv3State, sysmem, TYPE_MEMORY_REGION, + MemoryRegion *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c index b65f56f903..96a317a8ef 100644 --- a/hw/intc/arm_gicv3_dist.c +++ b/hw/intc/arm_gicv3_dist.c @@ -366,12 +366,15 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, return MEMTX_OK; case GICD_TYPER: { + bool lpi_supported = false; /* For this implementation: * No1N == 1 (1-of-N SPI interrupts not supported) * A3V == 1 (non-zero values of Affinity level 3 supported) * IDbits == 0xf (we support 16-bit interrupt identifiers) * DVIS == 0 (Direct virtual LPI injection not supported) - * LPIS == 0 (LPIs not supported) + * LPIS == 1 (LPIs are supported if affinity routing is enabled) + * num_LPIs == 0b00000 (bits [15:11],Number of LPIs as indicated + * by GICD_TYPER.IDbits) * MBIS == 0 (message-based SPIs not supported) * SecurityExtn == 1 if security extns supported * CPUNumber == 0 since for us ARE is always 1 @@ -385,8 +388,23 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, */ bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS); + /* + * With securityextn on,LPIs are supported when affinity routing + * is enabled for non-secure state and if off LPIs are supported + * when affinity routing is enabled. + */ + if (s->lpi_enable) { + if (sec_extn) { + lpi_supported = (s->gicd_ctlr & GICD_CTLR_ARE_NS); + } else { + lpi_supported = (s->gicd_ctlr & GICD_CTLR_ARE); + } + } + *data = (1 << 25) | (1 << 24) | (sec_extn << 10) | - (0xf << 19) | itlinesnumber; + (lpi_supported << GICD_TYPER_LPIS_OFFSET) | (GICD_TYPER_IDBITS << + GICD_TYPER_IDBITS_OFFSET) | itlinesnumber; + s->gicd_typer = *data; return MEMTX_OK; } case GICD_IIDR: diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 8645220d61..325b974e70 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -248,10 +248,16 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset, case GICR_CTLR: /* For our implementation, GICR_TYPER.DPGS is 0 and so all * the DPG bits are RAZ/WI. We don't do anything asynchronously, - * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't - * implement LPIs) so Enable_LPIs is RES0. So there are no writable - * bits for us. + * so UWP and RWP are RAZ/WI. GICR_TYPER.LPIS is 1 (we + * implement LPIs) so Enable_LPIs is programmable. */ + if (cs->gicr_typer & GICR_TYPER_PLPIS) { + if (value & GICR_CTLR_ENABLE_LPIS) { + cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS; + } else { + cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS; + } + } return MEMTX_OK; case GICR_STATUSR: /* RAZ/WI for our implementation */ @@ -275,6 +281,14 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset, cs->gicr_waker = value; return MEMTX_OK; case GICR_PROPBASER: + if (FIELD_EX64(value, GICR_PROPBASER, IDBITS) < + GICR_PROPBASER_IDBITS_THRESHOLD) { + cs->lpi_outofrange = true; + } + if (FIELD_EX64(value, GICR_PROPBASER, IDBITS) > GICD_TYPER_IDBITS) { + value &= ~R_GICR_PROPBASER_IDBITS_MASK; + value |= GICD_TYPER_IDBITS; + } cs->gicr_propbaser = deposit64(cs->gicr_propbaser, 0, 32, value); return MEMTX_OK; case GICR_PROPBASER + 4: @@ -397,6 +411,14 @@ static MemTxResult gicr_writell(GICv3CPUState *cs, hwaddr offset, { switch (offset) { case GICR_PROPBASER: + if (FIELD_EX64(value, GICR_PROPBASER, IDBITS) < + GICR_PROPBASER_IDBITS_THRESHOLD) { + cs->lpi_outofrange = true; + } + if (FIELD_EX64(value, GICR_PROPBASER, IDBITS) > GICD_TYPER_IDBITS) { + value &= ~R_GICR_PROPBASER_IDBITS_MASK; + value |= GICD_TYPER_IDBITS; + } cs->gicr_propbaser = value; return MEMTX_OK; case GICR_PENDBASER: diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index e9f9aa6722..a2718704d4 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -68,6 +68,9 @@ #define GICD_CTLR_E1NWF (1U << 7) #define GICD_CTLR_RWP (1U << 31) +#define GICD_TYPER_LPIS_OFFSET 17 +#define GICD_TYPER_IDBITS_OFFSET 19 +#define GICD_TYPER_IDBITS_MASK 0x1f /* 16 bits EventId */ #define GICD_TYPER_IDBITS 0xf @@ -126,6 +129,20 @@ #define GICR_WAKER_ProcessorSleep (1U << 1) #define GICR_WAKER_ChildrenAsleep (1U << 2) +FIELD(GICR_PROPBASER, IDBITS, 0, 5) +FIELD(GICR_PROPBASER, INNERCACHE, 7, 3) +FIELD(GICR_PROPBASER, SHAREABILITY, 10, 2) +FIELD(GICR_PROPBASER, PHYADDR, 12, 40) +FIELD(GICR_PROPBASER, OUTERCACHE, 56, 3) + +#define GICR_PROPBASER_IDBITS_THRESHOLD 0xd + +FIELD(GICR_PENDBASER, INNERCACHE, 7, 3) +FIELD(GICR_PENDBASER, SHAREABILITY, 10, 2) +FIELD(GICR_PENDBASER, PHYADDR, 16, 36) +FIELD(GICR_PENDBASER, OUTERCACHE, 56, 3) +FIELD(GICR_PENDBASER, PTZ, 62, 1) + #define ICC_CTLR_EL1_CBPR (1U << 0) #define ICC_CTLR_EL1_EOIMODE (1U << 1) #define ICC_CTLR_EL1_PMHE (1U << 6) diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 3a710592a9..db3989484d 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -175,6 +175,13 @@ struct GICv3CPUState { uint32_t gicr_nsacr; uint8_t gicr_ipriorityr[GIC_INTERNAL]; + /* + * flag to indicate LPIs are out of range + * since IDbits from GICR_PROPBASER is less + * than 0b1101 + */ + bool lpi_outofrange; + /* CPU interface */ uint64_t icc_sre_el1; uint64_t icc_ctlr_el1[2]; @@ -221,6 +228,7 @@ struct GICv3State { uint32_t num_cpu; uint32_t num_irq; uint32_t revision; + bool lpi_enable; bool security_extn; bool irq_reset_nonsecure; bool gicd_no_migration_shift_bug; From patchwork Thu Apr 1 02:41:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176977 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7AD7FC433B4 for ; Thu, 1 Apr 2021 02:49:43 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 147BD61057 for ; Thu, 1 Apr 2021 02:49:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 147BD61057 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:32836 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnOw-0003Ch-0a for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:49:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58488) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHa-0002re-S5 for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:06 -0400 Received: from mail-qk1-x733.google.com ([2607:f8b0:4864:20::733]:45711) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHT-0003An-Rm for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:06 -0400 Received: by mail-qk1-x733.google.com with SMTP id q3so853658qkq.12 for ; Wed, 31 Mar 2021 19:41:59 -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 :mime-version:content-transfer-encoding; bh=BH2Wx4yqn3rSWYD0hZ3gsX6NH7mvgc5o0D4iVxHx4R8=; b=IPv519x9Lv+rVoUlXFTvQFv/RRM+4bzdRVyWpXWt2VDh7Dxi7HD4EAS6MonPUl2UwJ ZrrzyCUtfQwMij2oXj+PFFSdm4btkfVOr3uBFDYe5aKCOSncSU8w1jd05qtYTubY7hjv qpbAi4lcAoFUSOl53eCnSKMXh3/+H/1/hWOuFGHEhVWri3qiy4XUFPNx3OUqSqk7Z7xg 3m8bvuPDKVZj80v6jep06RKW7Ns9HpZiPATU/NOcybeuBumWHoUwI4FksEdME4Q7EPpE Ww3Le1JOd2G8FPfmtpUJdjdc0qsXSXYNABlx0krhmgO1LPvxpUhyFvCnnrwULWY4pSjw YpPg== 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:mime-version:content-transfer-encoding; bh=BH2Wx4yqn3rSWYD0hZ3gsX6NH7mvgc5o0D4iVxHx4R8=; b=iGyQmq5BXJiZnNPUzVOkWBWdOOIGYb0yZuUn+qN3n6VfRqxIV05jntbCMzTgueItmI lGU2GyPV2JXmLd0Yc02AKvHQvG2uNI5aN0YVd4ChRNURtpvGiS7Xgm8kC8jy0kn9ckgk SWX+wnjnolN+806OxMJq3ZXhMvhwgiaAtJ/SKD6gPfvSaqWWhI++YhEzxZ0EDqG8HHS7 dlt8a2Q58WQgH8a9XnxzuWAAeD2KBIjF2FQQK9CMAg4eBsWz23JPW6q9o4MGpOnl4i5e 8jw00JJ9ZHumOZR/jg3Hh2SXK9KpJvpxaJE8pRzkWPPWkp7CgfreoNVVxpvhKEUqbqGL 6Dng== X-Gm-Message-State: AOAM531HGkuQ4Jged6KKkYeIzFV/PHS4E28bt8PQVe7dHcWwdJKVYaEA 68DyywMZhbB/10eyywFKqN2p+g== X-Google-Smtp-Source: ABdhPJxUUmOIWCmvwCs5tLRNiRwzSxxh1vhGx9VjGMmo03XqAbIyivjQSi9tYGmRbYqkXXzGYQdvUg== X-Received: by 2002:a37:615:: with SMTP id 21mr6270293qkg.421.1617244918643; Wed, 31 Mar 2021 19:41:58 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:58 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 6/8] hw/intc: GICv3 redistributor ITS processing Date: Wed, 31 Mar 2021 22:41:50 -0400 Message-Id: <20210401024152.203896-7-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::733; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x733.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Implemented lpi processing at redistributor to get lpi config info from lpi configuration table,determine priority,set pending state in lpi pending table and forward the lpi to cpuif.Added logic to invoke redistributor lpi processing with translated LPI which set/clear LPI from ITS device as part of ITS INT,CLEAR,DISCARD command and GITS_TRANSLATER processing. Signed-off-by: Shashi Mallela --- hw/intc/arm_gicv3.c | 6 ++ hw/intc/arm_gicv3_cpuif.c | 15 +++-- hw/intc/arm_gicv3_its.c | 9 ++- hw/intc/arm_gicv3_redist.c | 124 +++++++++++++++++++++++++++++++++++++ hw/intc/gicv3_internal.h | 9 +++ 5 files changed, 158 insertions(+), 5 deletions(-) diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c index 66eaa97198..618fa1af95 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c @@ -166,6 +166,12 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs) cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); } + if (cs->gic->lpi_enable) { + if (gicv3_redist_update_lpi(cs)) { + seenbetter = true; + } + } + /* If the best interrupt we just found would preempt whatever * was the previous best interrupt before this update, then * we know it's definitely the best one now. diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index 43ef1d7a84..c225b80f66 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -899,9 +899,14 @@ static void icc_activate_irq(GICv3CPUState *cs, int irq) cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0); gicv3_redist_update(cs); } else { - gicv3_gicd_active_set(cs->gic, irq); - gicv3_gicd_pending_clear(cs->gic, irq); - gicv3_update(cs->gic, irq, 1); + if (irq >= GICV3_LPI_INTID_START) { + gicv3_redist_lpi_pending(cs, irq, 0); + gicv3_redist_update(cs); + } else { + gicv3_gicd_active_set(cs->gic, irq); + gicv3_gicd_pending_clear(cs->gic, irq); + gicv3_update(cs->gic, irq, 1); + } } } @@ -1337,7 +1342,9 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri, * valid interrupt value read from the Interrupt Acknowledge * register" and so this is UNPREDICTABLE. We choose to ignore it. */ - return; + if (!(cs->gic->lpi_enable && (irq >= GICV3_LPI_INTID_START))) { + return; + } } if (icc_highest_active_group(cs) != grp) { diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 0e3f176809..41e1e8b2a8 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -226,6 +226,7 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t value, bool ite_valid = false; uint64_t cte = 0; bool cte_valid = false; + uint64_t rdbase; uint8_t buff[ITS_ITT_ENTRY_SIZE]; uint64_t itt_addr; @@ -278,12 +279,18 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t value, * since with a physical address the target address must be * 64KB aligned */ - + rdbase = (cte >> 1U) & RDBASE_MASK; /* * Current implementation only supports rdbase == procnum * Hence rdbase physical address is ignored */ } else { + rdbase = (cte >> 1U) & RDBASE_PROCNUM_MASK; + if ((cmd == CLEAR) || (cmd == DISCARD)) { + gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0); + } else { + gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1); + } if (cmd == DISCARD) { /* remove mapping from interrupt translation table */ diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 325b974e70..71c648a616 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -254,6 +254,8 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset, if (cs->gicr_typer & GICR_TYPER_PLPIS) { if (value & GICR_CTLR_ENABLE_LPIS) { cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS; + /* Check for any pending interr in pending table */ + gicv3_redist_update(cs); } else { cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS; } @@ -548,6 +550,128 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, return r; } +bool gicv3_redist_update_lpi(GICv3CPUState *cs) +{ + AddressSpace *as = &cs->gic->sysmem_as; + uint64_t lpict_baddr, lpipt_baddr; + uint32_t pendt_size = 0; + uint8_t lpite; + uint8_t prio, pend; + int i; + bool seenbetter = false; + + if ((!cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser || + !cs->gicr_pendbaser || cs->lpi_outofrange) { + return seenbetter; + } + + lpict_baddr = FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, PHYADDR); + lpict_baddr <<= R_GICR_PROPBASER_PHYADDR_SHIFT; + + lpipt_baddr = FIELD_EX64(cs->gicr_pendbaser, GICR_PENDBASER, PHYADDR); + lpipt_baddr <<= R_GICR_PENDBASER_PHYADDR_SHIFT; + + /* Determine the highest priority pending interrupt among LPIs */ + pendt_size = (1UL << (FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, + IDBITS) - 1)); + + for (i = 0; i < pendt_size; i++) { + address_space_read(as, lpipt_baddr + + (((GICV3_LPI_INTID_START + i) / 8) * sizeof(pend)), + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); + + if ((1 << ((GICV3_LPI_INTID_START + i) % 8)) & pend) { + address_space_read(as, lpict_baddr + (i * sizeof(lpite)), + MEMTXATTRS_UNSPECIFIED, &lpite, sizeof(lpite)); + + prio = ((lpite >> LPI_CTE_PRIORITY_OFFSET) & + LPI_CTE_PRIORITY_MASK); + prio &= LPI_PRIORITY_MASK; + + if (prio < cs->hppi.prio) { + cs->hppi.irq = GICV3_LPI_INTID_START + i; + cs->hppi.prio = prio; + /* LPIs are always non-secure Grp1 interrupts */ + cs->hppi.grp = GICV3_G1NS; + seenbetter = true; + } + } + } + return seenbetter; +} + +void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) +{ + AddressSpace *as = &cs->gic->sysmem_as; + uint64_t lpipt_baddr; + bool ispend = false; + uint8_t pend; + + /* + * get the bit value corresponding to this irq in the + * lpi pending table + */ + lpipt_baddr = FIELD_EX64(cs->gicr_pendbaser, GICR_PENDBASER, PHYADDR); + lpipt_baddr <<= R_GICR_PENDBASER_PHYADDR_SHIFT; + + address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)), + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); + ispend = ((pend >> (irq % 8)) & 0x1); + + if (ispend) { + if (!level) { + /* + * clear the pending bit and update the lpi pending table + */ + pend &= ~(1 << (irq % 8)); + + address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)), + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); + } + } else { + if (level) { + /* + * if pending bit is not already set for this irq,turn-on the + * pending bit and update the lpi pending table + */ + pend |= (1 << (irq % 8)); + + address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)), + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); + } + } +} + +void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) +{ + AddressSpace *as = &cs->gic->sysmem_as; + uint64_t lpict_baddr; + uint8_t lpite; + + if ((!cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser || + !cs->gicr_pendbaser || cs->lpi_outofrange) { + return; + } + + lpict_baddr = FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, PHYADDR); + lpict_baddr <<= R_GICR_PROPBASER_PHYADDR_SHIFT; + + /* get the lpi config table entry corresponding to this irq */ + address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) * + sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, + &lpite, sizeof(lpite)); + + /* check if this irq is enabled before proceeding further */ + if (!(lpite & LPI_CTE_ENABLED)) { + return; + } + + /* set/clear the pending bit for this irq */ + gicv3_redist_lpi_pending(cs, irq, level); + + gicv3_redist_update(cs); +} + void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level) { /* Update redistributor state for a change in an external PPI input line */ diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index a2718704d4..4c97c22850 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -306,6 +306,12 @@ FIELD(GITS_TYPER, CIL, 36, 1) #define L1TABLE_ENTRY_SIZE 8 +#define LPI_CTE_ENABLE_OFFSET 0 +#define LPI_CTE_ENABLED VALID_MASK +#define LPI_CTE_PRIORITY_OFFSET 2 +#define LPI_CTE_PRIORITY_MASK ((1U << 6) - 1) +#define LPI_PRIORITY_MASK 0xfc + #define GITS_CMDQ_ENTRY_SIZE 32 #define NUM_BYTES_IN_DW 8 @@ -444,6 +450,9 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, unsigned size, MemTxAttrs attrs); void gicv3_dist_set_irq(GICv3State *s, int irq, int level); void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level); +void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level); +void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level); +bool gicv3_redist_update_lpi(GICv3CPUState *cs); void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); void gicv3_init_cpuif(GICv3State *s); From patchwork Thu Apr 1 02:41:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176969 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02C09C433ED for ; Thu, 1 Apr 2021 02:45:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A4686608FE for ; Thu, 1 Apr 2021 02:45:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A4686608FE Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51076 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnLE-0007VA-R5 for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:45:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58470) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHZ-0002p3-J5 for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:05 -0400 Received: from mail-qk1-x730.google.com ([2607:f8b0:4864:20::730]:35367) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHU-0003BZ-C2 for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:05 -0400 Received: by mail-qk1-x730.google.com with SMTP id i9so924218qka.2 for ; Wed, 31 Mar 2021 19:41:59 -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 :mime-version:content-transfer-encoding; bh=dDFLsvyLe8lLl4nZKmWov7o0SG/Q1sJrDdZtdR5zH+8=; b=InR1Q00OkWFeCk7332+QyLnJG2pqndgyUXZKQX3bQF4ied5UYxs8QQXyVXrItiF4KX ezO2oGXXuQpobrKdtJqq9FhKi6pG9BzQohxy6qMQatauVPRexlTb6lkBAadD6tQt69Cd uKEfHjFqnb4Ol/Tp5uL/MCmglgxrhMK79bRMF/jiFLvVw88gqlg88d/NrtltyqLejYuf SBUi4PqqQUqO/0OUx4F9n1qJrxgEo4CZSMcH1RKZg11JVXKZDTU+tNAADYRNsAzaTwaP hNTqRPVcA5dDrXstxtXW7cJueAdWvleNmk1yG9mh4FPHHuwBNQan6yALfYz0I0JUi7co ZMkQ== 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:mime-version:content-transfer-encoding; bh=dDFLsvyLe8lLl4nZKmWov7o0SG/Q1sJrDdZtdR5zH+8=; b=kEXmzMTyjIKgtgwqTHuk4GVtWYhrezkKTg7cgzvh9ZBSHMIJbgZGcXetAZIx5ZHRon 4INp0YfT3FkuAlez0eVkpqLmyZsB4cBjpyqkjFaAJyYS946Ipxhl2INcH7pe0mX0MBJW sPR1uqyTabgsxiJWezUBxJQrlFRpEyb0ikdob3FglP3Sow9wXn6qF3BQshlnNq3yqMai wVOdeIE1aJfMn3dh8J0RZxEa6ByuLBtncCUuNUvQb4WuKHvLg3fZIgdLmSxqJ/xLX8iG ACFcymow+F4sgK/q1LdkCnTvVvvAJzWmSpxR2Nkla8l5WYB+Vz/OC0sgv4y/JnUUg2hc 7IKg== X-Gm-Message-State: AOAM531xELPdYnNEA7dks6Ts60Z4Rj3cxAlaAXO/QA6unUmSIbhSUfsK IJYp2OWS+e7Jh+E+9fBFyEUvWg== X-Google-Smtp-Source: ABdhPJx/Jz4h2lVxTtgLlXlUv4pU/Qhtbcvrm774zvESoQa71XgmW71b6wrIpiB/k/tKuwNEOkeYiA== X-Received: by 2002:a37:a211:: with SMTP id l17mr6439009qke.195.1617244919306; Wed, 31 Mar 2021 19:41:59 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:59 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 7/8] hw/arm/sbsa-ref: add ITS support in SBSA GIC Date: Wed, 31 Mar 2021 22:41:51 -0400 Message-Id: <20210401024152.203896-8-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::730; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x730.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Included creation of ITS as part of SBSA platform GIC initialization. Signed-off-by: Shashi Mallela Reviewed-by: Peter Maydell --- hw/arm/sbsa-ref.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 88dfb2284c..d05cbcae48 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -35,7 +35,7 @@ #include "hw/boards.h" #include "hw/ide/internal.h" #include "hw/ide/ahci_internal.h" -#include "hw/intc/arm_gicv3_common.h" +#include "hw/intc/arm_gicv3_its_common.h" #include "hw/loader.h" #include "hw/pci-host/gpex.h" #include "hw/qdev-properties.h" @@ -65,6 +65,7 @@ enum { SBSA_CPUPERIPHS, SBSA_GIC_DIST, SBSA_GIC_REDIST, + SBSA_GIC_ITS, SBSA_SECURE_EC, SBSA_GWDT, SBSA_GWDT_REFRESH, @@ -108,6 +109,7 @@ static const MemMapEntry sbsa_ref_memmap[] = { [SBSA_CPUPERIPHS] = { 0x40000000, 0x00040000 }, [SBSA_GIC_DIST] = { 0x40060000, 0x00010000 }, [SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 }, + [SBSA_GIC_ITS] = { 0x44090000, 0x00020000 }, [SBSA_SECURE_EC] = { 0x50000000, 0x00001000 }, [SBSA_GWDT_REFRESH] = { 0x50010000, 0x00001000 }, [SBSA_GWDT_CONTROL] = { 0x50011000, 0x00001000 }, @@ -378,7 +380,20 @@ static void create_secure_ram(SBSAMachineState *sms, memory_region_add_subregion(secure_sysmem, base, secram); } -static void create_gic(SBSAMachineState *sms) +static void create_its(SBSAMachineState *sms) +{ + DeviceState *dev; + + dev = qdev_new(TYPE_ARM_GICV3_ITS); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + + object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(sms->gic), + &error_abort); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, sbsa_ref_memmap[SBSA_GIC_ITS].base); +} + +static void create_gic(SBSAMachineState *sms, MemoryRegion *mem) { unsigned int smp_cpus = MACHINE(sms)->smp.cpus; SysBusDevice *gicbusdev; @@ -405,6 +420,10 @@ static void create_gic(SBSAMachineState *sms) qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1); qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count); + object_property_set_link(OBJECT(sms->gic), "sysmem", OBJECT(mem), + &error_fatal); + qdev_prop_set_bit(sms->gic, "has-lpi", true); + gicbusdev = SYS_BUS_DEVICE(sms->gic); sysbus_realize_and_unref(gicbusdev, &error_fatal); sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base); @@ -451,6 +470,7 @@ static void create_gic(SBSAMachineState *sms) sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus, qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); } + create_its(sms); } static void create_uart(const SBSAMachineState *sms, int uart, @@ -763,7 +783,7 @@ static void sbsa_ref_init(MachineState *machine) create_secure_ram(sms, secure_sysmem); - create_gic(sms); + create_gic(sms, sysmem); create_uart(sms, SBSA_UART, sysmem, serial_hd(0)); create_uart(sms, SBSA_SECURE_UART, secure_sysmem, serial_hd(1)); From patchwork Thu Apr 1 02:41:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shashi Mallela X-Patchwork-Id: 12176973 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1535AC433ED for ; Thu, 1 Apr 2021 02:48:05 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 74C7661001 for ; Thu, 1 Apr 2021 02:48:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 74C7661001 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56564 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRnNL-0001J5-GT for qemu-devel@archiver.kernel.org; Wed, 31 Mar 2021 22:48:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58486) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRnHa-0002rK-OI for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:06 -0400 Received: from mail-qk1-x729.google.com ([2607:f8b0:4864:20::729]:42646) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lRnHV-0003Cb-3H for qemu-devel@nongnu.org; Wed, 31 Mar 2021 22:42:06 -0400 Received: by mail-qk1-x729.google.com with SMTP id y5so875309qkl.9 for ; Wed, 31 Mar 2021 19:42:00 -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 :mime-version:content-transfer-encoding; bh=36CRRigRDg6z7Ps/zHm2nFOe3o4QS1w0QeVs5IpQt88=; b=D68RcJiw9z0nkC+YTho/xYvi6Gl34ideQTD1NULJeMec2XASt3Z8WKABH+PRJf00mD KTdzP8LDslcwdJS+E1zVMCpeaAMWN1lB5/m3iQtaPoevb9DmFkViwA72MSemPeV7aaAN O4HgyS5QyqPtkKXAjzPM7sPz0a4vB4WzUq9O7GpBmN71TO73HcCZdmiqOsz1Ce+UmrxL Spjhyw58ChQIiGdjJFmSzzEVjkJah8oP3kl2jXsz/FOgL3uSKgL7nCBw4p9+6KeVGW4N /uqleBhiOxc2W7QmBG65uguew3ImzEPolJBwSGH2InnomSZaMwG8re0fwmvU9aqV432i pXcw== 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:mime-version:content-transfer-encoding; bh=36CRRigRDg6z7Ps/zHm2nFOe3o4QS1w0QeVs5IpQt88=; b=VQEPvKBbULr+RqQiqsXAfLsAzbkg7i/QruvldifQSMRIiDkNaDIWaeOr5t9sAHnf5J msPF0pNa1mY/E6nZwPwZzGEQ7Ro6o7mS+vRo3BqSLIyLRMHMxLrigxT2qrdslGEdMDrv 6/jcrDmqbOhnRpTNtsk+zSd2bEEXpLKTGxxd3mqCjg/L8LKfZ3/8AyNVOl0gefgomFo6 uyTVvf/J/iq3ykyOXhJ6dK0ZlBNK7HXsOAlg/JGBeSU64vZD0tuz3bx3gGtgKhqeS2rD kENvXpF5aW2+9t5C1Gxx9k/CQUm4UTB8FUudwsTldOch2Yumrgb2GhRtgo29XcVtIXyq 6YSw== X-Gm-Message-State: AOAM532HUl92N9rbuX4l/Jz4oDmpEVpfrpmOJ58RWmA2H86nMrnL18dC mfsGe3GTem/qkaGCcNxctlvBRA== X-Google-Smtp-Source: ABdhPJzJqbH+IcDfBfH9ORFpvkEK0VwLuylAw6B+ZoABabqP9LGk8CzyWlug61Jzk162w/P/RYmVzQ== X-Received: by 2002:a05:620a:14b3:: with SMTP id x19mr6434890qkj.384.1617244919937; Wed, 31 Mar 2021 19:41:59 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-23-174-92-28-28.dsl.bell.ca. [174.92.28.28]) by smtp.googlemail.com with ESMTPSA id a8sm2525707qtx.9.2021.03.31.19.41.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 19:41:59 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v2 8/8] hw/arm/virt: add ITS support in virt GIC Date: Wed, 31 Mar 2021 22:41:52 -0400 Message-Id: <20210401024152.203896-9-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210401024152.203896-1-shashi.mallela@linaro.org> References: <20210401024152.203896-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::729; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x729.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Included creation of ITS as part of virt platform GIC initialization.This Emulated ITS model now co-exists with kvm ITS and is enabled in absence of kvm irq kernel support in a platform. Signed-off-by: Shashi Mallela --- hw/arm/virt.c | 10 ++++++++-- target/arm/kvm_arm.h | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index aa2bbd14e0..77cf2db90f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -622,7 +622,7 @@ static void create_v2m(VirtMachineState *vms) vms->msi_controller = VIRT_MSI_CTRL_GICV2M; } -static void create_gic(VirtMachineState *vms) +static void create_gic(VirtMachineState *vms, MemoryRegion *mem) { MachineState *ms = MACHINE(vms); /* We create a standalone GIC */ @@ -656,6 +656,12 @@ static void create_gic(VirtMachineState *vms) nb_redist_regions); qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count); + if (!kvm_irqchip_in_kernel()) { + object_property_set_link(OBJECT(vms->gic), "sysmem", OBJECT(mem), + &error_fatal); + qdev_prop_set_bit(vms->gic, "has-lpi", true); + } + if (nb_redist_regions == 2) { uint32_t redist1_capacity = vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE; @@ -2039,7 +2045,7 @@ static void machvirt_init(MachineState *machine) virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); - create_gic(vms); + create_gic(vms, sysmem); virt_cpu_post_init(vms, sysmem); diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 34f8daa377..0613454975 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -525,8 +525,8 @@ static inline const char *its_class_name(void) /* KVM implementation requires this capability */ return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL; } else { - /* Software emulation is not implemented yet */ - return NULL; + /* Software emulation based model */ + return "arm-gicv3-its"; } }