From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by 2002:a19:4310:0:0:0:0:0 with SMTP id q16csp519003lfa; Wed, 2 Jun 2021 11:03:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyU1U/s6oT9uWdb/3fN3PNvGUxA3DvTdZbDEn/It9PKE7FHSSt910WB0weLGxVboHuRuqai X-Received: by 2002:a17:906:6d90:: with SMTP id h16mr20069279ejt.351.1622657033531; Wed, 02 Jun 2021 11:03:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622657033; cv=none; d=google.com; s=arc-20160816; b=Wom8I/UfmZ+GP0dI5WiGGNsYVrRaTg53FWFMj81hY2B5H6U264wKmGEW/uij/gd8Xn fsJSsOyLewMyv/ctazO0SiHnTVnbMtYcHJiSvW7e/ObSeh9oP2Y98ktuATsfihbB5YqU 8QyjwmzLVl+wyyOFW5mxVlgdk+mPhjpdgcZzHGJaIy053+iVcdWhHG6tgFKMBtHNP7lz D2CpmmUVr1Y1clKwpyHtHJkHk0F8JG1eOR8s+xf4BwPEkiei/yATjOOlWAH5zMZPHvLa YiYcTXGeG9ffIb2Avy0YXdIzdn+SZW5it295q2taBbweH5AZPB3wqfJskN+jpgl6uEVV K2wQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=C/SlYHFsBbOx8B80G1ZIY7V5qyExe6SSrrZ+O8mGBQ0=; b=yuuKERmc5mcfnoAspYMnW/LPGFhYLnkkZt4luLlDeWJFAtxXmf542F1Rn2WYbsYuBE fMjrXUqfekrYr149wCViSVhjkUlnA1O+oIWwTDmAObMQzK8mYg28LstA+0LP8yENshJi X0Y09R3FKkp6iUG/mCcF1oYW5VriCe8JP7fGFpbR/IaYvoUXZOk+DJSc+ycVMXi4vRUs AmKdqTCAyz4Uo2MWvLIr9jvxXZO5hGZuK/7rAjeI4zIkDgWX3LpoMofE/AltKxB6dGU7 JwPIb1/ixASQI2ARVxiFQvJRZbxBPP30ZQjuAZc4lQW78Hd/b+0EeHkG5RIVX5jkgVp1 6zGw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CUmUnDw5; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id h11si483815edz.24.2021.06.02.11.03.53 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Wed, 02 Jun 2021 11:03:53 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CUmUnDw5; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:49086 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1loVDc-0005f1-Fk for alex.bennee@linaro.org; Wed, 02 Jun 2021 14:03:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51130) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loVAk-0008AZ-4H for qemu-arm@nongnu.org; Wed, 02 Jun 2021 14:00:54 -0400 Received: from mail-qk1-x731.google.com ([2607:f8b0:4864:20::731]:45846) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1loVAf-0006aO-A7 for qemu-arm@nongnu.org; Wed, 02 Jun 2021 14:00:53 -0400 Received: by mail-qk1-x731.google.com with SMTP id 65so1847245qkg.12 for ; Wed, 02 Jun 2021 11:00:47 -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=C/SlYHFsBbOx8B80G1ZIY7V5qyExe6SSrrZ+O8mGBQ0=; b=CUmUnDw5gRcdP+mQYS9CceLNLpIFSAfd8T1KCXj6R2R9EWiuTZXjXIAHUsGxJGWIWU 8adypKYUKuj2Hl7k37chohASwg6+zFq0OEnA1+sFQmhYKX3Qw+yt+5JpAMhbfbNruXIo WS3ZjC0JsTH5rvyCvfMMXm/wAE1fZ79n9iV9DV6HepETy0HA0FRQsYo+7z5KSM9kCD70 OWd/M1MOYUIgeoHURdCUFyBWoSTTcvnJ4uR8NUmYYw9ccmaYMVuuD0TfTE4FWlOicwws jIyzcsAeaYDS11m+rVVSfx2PmvAw+rAv7/WDpXT5QKUmByJadZ2DBPgsy7yISorEG/Mv n3jQ== 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=C/SlYHFsBbOx8B80G1ZIY7V5qyExe6SSrrZ+O8mGBQ0=; b=d1T3ToGmCBqURuv3JKLaSV3Q+ddwNpWw4fmagrAAHbyFSpAIh28vkC2Gs5BYwGDf7z uANRoflNpItnDVNSfNEtaEdmGnSj8CFBhP5CCo78hIvlGrudRMKmKXzW4V13Jf/QY/A3 jf9f0LHOoDIpn8nt7zgRePQq0IR/b926Gxl8sazC8c2ggHigzdregcOi6pmUlux7zdhU vEg1XUc10EOcDurvCm0TH840HOi144igroqgBE623URJetBIzu3IwhzKBIOsXYqyT2nQ cbkejLR9HCsh8z0BCI9iAbaAfM904T/7mSTPFUls9czsWuHJrD2TbqsA9djycsSCvZuh qJBg== X-Gm-Message-State: AOAM531/iTxRTLO/oEFjzI6xEb8amKf3L4pTNj/AGdEWxesTeoszyQWl tt1bBgagyPQ2FSuPWamdiHEHLOybgZgZiA== X-Received: by 2002:a37:ac17:: with SMTP id e23mr28975511qkm.184.1622656846655; Wed, 02 Jun 2021 11:00:46 -0700 (PDT) Received: from localhost.localdomain (bras-base-stsvon1503w-grc-21-142-114-142-78.dsl.bell.ca. [142.114.142.78]) by smtp.googlemail.com with ESMTPSA id 97sm273044qte.20.2021.06.02.11.00.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jun 2021 11:00:46 -0700 (PDT) From: Shashi Mallela To: peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com Subject: [PATCH v4 3/8] hw/intc: GICv3 ITS command queue framework Date: Wed, 2 Jun 2021 14:00:37 -0400 Message-Id: <20210602180042.111347-4-shashi.mallela@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602180042.111347-1-shashi.mallela@linaro.org> References: <20210602180042.111347-1-shashi.mallela@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=2607:f8b0:4864:20::731; envelope-from=shashi.mallela@linaro.org; helo=mail-qk1-x731.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-arm@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-arm-bounces+alex.bennee=linaro.org@nongnu.org Sender: "Qemu-arm" X-TUID: nBIoBTzX8UXV 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 | 295 +++++++++++++++++++++++++++++++++++++++ hw/intc/gicv3_internal.h | 37 +++++ 2 files changed, 332 insertions(+) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index af60f19c98..6551c577b3 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -49,6 +49,295 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz) return result; } +static MemTxResult update_cte(GICv3ITSState *s, uint16_t icid, bool valid, + uint64_t rdbase) +{ + AddressSpace *as = &s->gicv3->dma_as; + uint64_t value; + uint64_t l2t_addr; + bool valid_l2t; + uint32_t l2t_id; + uint32_t max_l2_entries; + uint64_t cte = 0; + MemTxResult res = MEMTX_OK; + + if (!s->ct.valid) { + return res; + } + + if (valid) { + /* add mapping entry to collection table */ + cte = (valid & VALID_MASK) | + ((rdbase & RDBASE_PROCNUM_MASK) << 1ULL); + } + + /* + * The specification defines the format of level 1 entries of a + * 2-level table, but the format of level 2 entries and the format + * of flat-mapped tables is IMPDEF. + */ + if (s->ct.indirect) { + l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE); + + value = address_space_ldq_le(as, + s->ct.base_addr + + (l2t_id * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, &res); + + if (res != MEMTX_OK) { + return res; + } + + valid_l2t = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid_l2t) { + max_l2_entries = s->ct.page_sz / s->ct.entry_sz; + + l2t_addr = value & ((1ULL << 51) - 1); + + address_space_stq_le(as, l2t_addr + + ((icid % max_l2_entries) * GITS_CTE_SIZE), + cte, MEMTXATTRS_UNSPECIFIED, &res); + } + } else { + /* Flat level table */ + address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE), + cte, MEMTXATTRS_UNSPECIFIED, &res); + } + return res; +} + +static MemTxResult process_mapc(GICv3ITSState *s, uint32_t offset) +{ + AddressSpace *as = &s->gicv3->dma_as; + uint16_t icid; + uint64_t rdbase; + bool valid; + MemTxResult res = MEMTX_OK; + 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); + + if (res != MEMTX_OK) { + return res; + } + + icid = value & ICID_MASK; + + rdbase = (value >> R_MAPC_RDBASE_SHIFT) & RDBASE_PROCNUM_MASK; + + valid = (value >> VALID_SHIFT) & VALID_MASK; + + if ((icid > s->ct.max_collids) || (rdbase > s->gicv3->num_cpu)) { + qemu_log_mask(LOG_GUEST_ERROR, + "ITS MAPC: invalid collection table attributes " + "icid %d rdbase %lu\n", icid, rdbase); + /* + * in this implementation,in case of error + * we ignore this command and move onto the next + * command in the queue + */ + } else { + res = update_cte(s, icid, valid, rdbase); + } + + return res; +} + +static MemTxResult update_dte(GICv3ITSState *s, uint32_t devid, bool valid, + uint8_t size, uint64_t itt_addr) +{ + AddressSpace *as = &s->gicv3->dma_as; + uint64_t value; + uint64_t l2t_addr; + bool valid_l2t; + uint32_t l2t_id; + uint32_t max_l2_entries; + uint64_t dte = 0; + MemTxResult res = MEMTX_OK; + + if (s->dt.valid) { + if (valid) { + /* add mapping entry to device table */ + dte = (valid & VALID_MASK) | + ((size & SIZE_MASK) << 1U) | + ((itt_addr & ITTADDR_MASK) << 6ULL); + } + } else { + return res; + } + + /* + * The specification defines the format of level 1 entries of a + * 2-level table, but the format of level 2 entries and the format + * of flat-mapped tables is IMPDEF. + */ + if (s->dt.indirect) { + l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE); + + value = address_space_ldq_le(as, + s->dt.base_addr + + (l2t_id * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, &res); + + if (res != MEMTX_OK) { + return res; + } + + valid_l2t = (value >> VALID_SHIFT) & VALID_MASK; + + if (valid_l2t) { + max_l2_entries = s->dt.page_sz / s->dt.entry_sz; + + l2t_addr = value & ((1ULL << 51) - 1); + + address_space_stq_le(as, l2t_addr + + ((devid % max_l2_entries) * GITS_DTE_SIZE), + dte, MEMTXATTRS_UNSPECIFIED, &res); + } + } else { + /* Flat level table */ + address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE), + dte, MEMTXATTRS_UNSPECIFIED, &res); + } + return res; +} + +static MemTxResult process_mapd(GICv3ITSState *s, uint64_t value, + uint32_t offset) +{ + AddressSpace *as = &s->gicv3->dma_as; + uint32_t devid; + uint8_t size; + uint64_t itt_addr; + bool valid; + MemTxResult res = MEMTX_OK; + + devid = (value >> DEVID_SHIFT) & DEVID_MASK; + + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + + if (res != MEMTX_OK) { + return res; + } + + size = (value & SIZE_MASK); + + offset += NUM_BYTES_IN_DW; + value = address_space_ldq_le(as, s->cq.base_addr + offset, + MEMTXATTRS_UNSPECIFIED, &res); + + if (res != MEMTX_OK) { + return res; + } + + itt_addr = (value >> ITTADDR_SHIFT) & ITTADDR_MASK; + + valid = (value >> VALID_SHIFT) & VALID_MASK; + + if ((devid > s->dt.max_devids) || + (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { + qemu_log_mask(LOG_GUEST_ERROR, + "ITS MAPD: invalid device table attributes " + "devid %d or size %d\n", devid, size); + /* + * in this implementation, in case of error + * we ignore this command and move onto the next + * command in the queue + */ + } else { + res = update_dte(s, devid, valid, size, itt_addr); + } + + return res; +} + +/* + * Current implementation blocks until all + * commands are processed + */ +static void 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->dma_as; + MemTxResult res = MEMTX_OK; + uint8_t cmd; + + if (!(s->ctlr & ITS_CTLR_ENABLED)) { + return; + } + + 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); + return; + } + + 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: + /* + * 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. + * Hence no further processing is required for SYNC command. + */ + 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 { + /* + * in this implementation,in case of dma read/write error + * we stall the command processing + */ + s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %x cmd processing failed!!\n", __func__, cmd); + break; + } + } +} + static void extract_table_params(GICv3ITSState *s) { uint16_t num_pages = 0; @@ -226,6 +515,9 @@ static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset, case GITS_CWRITER: s->cwriter = deposit64(s->cwriter, 0, 32, (value & ~R_GITS_CWRITER_RETRY_MASK)); + if (s->cwriter != s->creadr) { + process_cmdq(s); + } break; case GITS_CWRITER + 4: s->cwriter = deposit64(s->cwriter, 32, 32, @@ -346,6 +638,9 @@ static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset, break; case GITS_CWRITER: s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK; + if (s->cwriter != s->creadr) { + process_cmdq(s); + } break; case GITS_CREADR: case GITS_TYPER: diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index d6aaa94e4c..0932a30560 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -253,6 +253,9 @@ 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) @@ -289,6 +292,40 @@ 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_LENGTH 16 +#define ICID_MASK ((1U << ICID_LENGTH) - 1) +FIELD(MAPC, RDBASE, 16, 32) + +#define RDBASE_PROCNUM_LENGTH 16 +#define RDBASE_PROCNUM_MASK ((1ULL << RDBASE_PROCNUM_LENGTH) - 1) + +#define DEVID_SHIFT 32 +#define DEVID_LENGTH 32 +#define DEVID_MASK ((1ULL << DEVID_LENGTH) - 1) + +/* MAPD command fields */ +#define ITTADDR_LENGTH 44 +#define ITTADDR_SHIFT 8 +#define ITTADDR_MASK ((1ULL << ITTADDR_LENGTH) - 1) +#define SIZE_MASK 0x1f + +#define VALID_SHIFT 63 +#define VALID_MASK 1ULL /** * Default features advertised by this version of ITS -- 2.27.0