From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655215; cv=none; d=zohomail.com; s=zohoarc; b=eRtsnSgTrYnaE68XRgjr3iwYeLtGcF72MpoZ1FyFZ37qW5htqj5Hzuxd6J/cykGiehOZg3WIP/GIGgBK7b4RzLYU4YKhF3HIxVos3avr97XZRcE/6PP6d1qRmirrw0Rr2CvLgLsyuDPXeG55OnOvVo2ASCHf+PGupmmQ0OWYliU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655215; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=59PDeabW57Atf4QewYFYLbLETvC3v4AbC3AOLWtCo+E=; b=UxyeLUHTmF4O58pGzTC7SSTFwjGQUzGiPGayKl7bPAaCb3I0YUVyc1gXF1dycXXh5FeOL2YP/gLJSuZtoA2s1VilQJ5H4KKSiWSl70qfUVsiBI+avPsN+1lrMI11amBr/4FForRrmG1JbmdMXvt9EyYlIQwOmC3Nt8LCPNkaYFY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 179265521534423.870183954286063; Thu, 22 Oct 2026 00:46:55 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnUK-0007FJ-2U; Thu, 22 Oct 2026 03:45:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3Db_ZagoKClAABs53wG1zCy66y3w.u648w4C-vwDw3565y5C.69y@flex--stanleyjhu.bounces.google.com>) id 1xJnUJ-0007Ez-08 for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:23 -0400 Received: from mail-pj1-x1045.google.com ([2607:f8b0:4864:20::1045]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3Db_ZagoKClAABs53wG1zCy66y3w.u648w4C-vwDw3565y5C.69y@flex--stanleyjhu.bounces.google.com>) id 1xJnUG-0002G4-FF for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:22 -0400 Received: by mail-pj1-x1045.google.com with SMTP id 98e67ed59e1d1-3acc98e3b3cso1563658a91.3 for ; Thu, 22 Oct 2026 00:45:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655118; x=1793259918; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=59PDeabW57Atf4QewYFYLbLETvC3v4AbC3AOLWtCo+E=; b=v7SHuDzIhHSAutNvYxk4Zjpvf1D88w6hz7IoSW1RzqaE1Q4aRI098QXrCSfzkbESTI 42KI/lE+6+AbqJf071trpitbaNP576+8BktlVZ1C5EoHyu/QpkwfcMd44tuLL5YoJb9X AYKECNEsqrrG6d845fGiCA2gQhWJiYNncvTxlxplJyeKmQjSBNBnNE4dQ+Bkf0NqBtc8 TzpR/bd3sdbNy9ny5Mn0SO9c/hkbgagKUTNbR3DNoOTkubDkUIKiLh9ouaORDOl7tofP UVXxYH72Zp2iTCcR/WVXacqizZpuOKtnXHg2JrOSFyn6SCM9WM0fqDw0L8+dlV7b8MwR P+/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655118; x=1793259918; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=59PDeabW57Atf4QewYFYLbLETvC3v4AbC3AOLWtCo+E=; b=xcQYuVPnRo920M53MGHjml7YoHhmCt5+O2f8BK+7og4+YZUZwqf4p/X4rafe2KPHFi fD5jrdAEUKQX3xwV5E78BnyndjvCKWgzh+o4/tkvEFjC9SML0Jf9SopiQBlTUTJIHvQt xnoFeoOYkzGGlLpwP58Cu1nzRyNeVfTxP7JvJp5T78WEZZLbzwpX6yFTZXJmUlJtHNv+ Cxmk+ctovWiPrRo0SdUZ/VtRQBATCSyl7EXvX1UDRPsBbyygOnFcuv4hmlmtxHcwc60B Z9+3x9iaCOYbcyBDsN5vM8AJSg091ReOlG4Hb3peyVl4WPVcyhBCNue/H5ZxqFtqARyS Hd9w== X-Gm-Message-State: AFq9FYJcezKT8xjoMs19IJfIV1pdLNOHjyZNWPneWpM/ClvqbFyWdoDz xKc3DBChOoQr9YGwWg6cfeoORjgnBAzvlsDuFZzE+kSEaWKPp8T4j8I/YT+wp/BLLND5jEvgbk1 UN67oxJaeGMEHTL0xMAIK3w== X-Received: from pgfd4-n2.prod.google.com ([2002:a05:6a02:6544:20b0:cd6:db2:b293]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4d01:b0:3a8:92a3:8baa with SMTP id 98e67ed59e1d1-3ad86d50bfbmr3960650a91.27.1792655117426; Thu, 22 Oct 2026 00:45:17 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:06 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-2-stanleyjhu@google.com> Subject: [PATCH v2 1/8] hw/ufs: Add experimental fault injection properties for holding requests From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1045; envelope-from=3Db_ZagoKClAABs53wG1zCy66y3w.u648w4C-vwDw3565y5C.69y@flex--stanleyjhu.bounces.google.com; helo=mail-pj1-x1045.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655216640158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add experimental properties x-fault-inject-tag and x-fault-inject-mode to ufs-pci and ufs-sysbus devices for testing host driver error handling and recovery routines. When x-fault-inject-tag is set to a specific tag (0..255), the controller holds the matching SCSI command request in u->held_req without completing it. When x-fault-inject-tag is set to 0xfffffffe (UFS_FAULT_INJECT_TAG_ANY), the controller intercepts the first READ_10 or WRITE_10 command with LBA >=3D 512, skipping boot-time metadata reads. The default value is 0xffffffff (UFS_FAULT_INJECT_TAG_NONE), which disables fault injection. Both properties can be changed at runtime through QOM (for example QMP qom-set). A held request is released on HCE reset. Task management handling for held requests follows in the next patch. Signed-off-by: Stanley Jhu --- hw/ufs/trace-events | 3 + hw/ufs/ufs-pci.c | 6 ++ hw/ufs/ufs-sysbus.c | 6 ++ hw/ufs/ufs.c | 229 ++++++++++++++++++++++++++++++++++++++++++++ hw/ufs/ufs.h | 58 +++++++++++ 5 files changed, 302 insertions(+) diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events index c5c148be91..a26529a1ed 100644 --- a/hw/ufs/trace-events +++ b/hw/ufs/trace-events @@ -16,6 +16,9 @@ ufs_mcq_create_sq(uint8_t sqid, uint8_t cqid, uint64_t ad= dr, uint16_t size) "mcq ufs_mcq_create_cq(uint8_t cqid, uint64_t addr, uint16_t size) "mcq create = cq cqid %"PRIu8", addr 0x%"PRIx64", size %"PRIu16"" ufs_write_mcq_op_reg(uint8_t qid, uint32_t offset, uint32_t data) "qid %"P= RIu8", offset 0x%"PRIx32", data 0x%"PRIx32"" ufs_process_tmr(uint8_t func, uint32_t tag, uint8_t resp) "query_func 0x%"= PRIx8", task_tag %"PRIu32", tm_resp 0x%"PRIx8"" +ufs_fault_inject_hold_req(uint8_t tag, uint32_t lba) "held command tag %"P= RIu8", lba %"PRIu32"" +ufs_fault_inject_set_tag(uint32_t tag) "fault-inject-tag set to 0x%"PRIx32= "" +ufs_fault_inject_set_mode(const char *mode) "fault-inject-mode set to %s" ufs_hce_reset(void) "HCE 1 -> 0 reset: cancelling BHs, resetting MCQ and r= equest lists" =20 # error condition diff --git a/hw/ufs/ufs-pci.c b/hw/ufs/ufs-pci.c index 8abd7d98e3..504a63bef9 100644 --- a/hw/ufs/ufs-pci.c +++ b/hw/ufs/ufs-pci.c @@ -72,6 +72,12 @@ static const Property ufs_pci_props[] =3D { 0x400), DEFINE_PROP_UINT32("wb-min-size", UfsPciState, ufs.params.wb_min_size, 0x100), + DEFINE_PROP_UNSIGNED("x-fault-inject-tag", UfsPciState, + ufs.params.fault_inject_tag, UFS_FAULT_INJECT_TAG= _NONE, + ufs_prop_fault_inject_tag, uint32_t), + DEFINE_PROP("x-fault-inject-mode", UfsPciState, + ufs.params.fault_inject_mode, ufs_prop_fault_inject_mode, + char *), }; =20 static const VMStateDescription ufs_pci_vmstate =3D { diff --git a/hw/ufs/ufs-sysbus.c b/hw/ufs/ufs-sysbus.c index 84de2e95ac..9de31557e7 100644 --- a/hw/ufs/ufs-sysbus.c +++ b/hw/ufs/ufs-sysbus.c @@ -45,6 +45,12 @@ static const Property ufs_sysbus_props[] =3D { 0x400), DEFINE_PROP_UINT32("wb-min-size", SysbusUfsState, ufs.params.wb_min_si= ze, 0x100), + DEFINE_PROP_UNSIGNED("x-fault-inject-tag", SysbusUfsState, + ufs.params.fault_inject_tag, UFS_FAULT_INJECT_TAG= _NONE, + ufs_prop_fault_inject_tag, uint32_t), + DEFINE_PROP("x-fault-inject-mode", SysbusUfsState, + ufs.params.fault_inject_mode, ufs_prop_fault_inject_mode, + char *), }; =20 static const VMStateDescription ufs_sysbus_vmstate =3D { diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index cd28f97a12..f356818375 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -15,6 +15,7 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/visitor.h" #include "scsi/constants.h" #include "hw/core/irq.h" #include "trace.h" @@ -778,6 +779,66 @@ static bool ufs_mcq_delete_cq(UfsHc *u, uint8_t qid) return true; } =20 +static void ufs_fault_inject_init(UfsHc *u) +{ + u->active_fault_inject_tag =3D u->params.fault_inject_tag; + u->held_req =3D NULL; +} + +static void ufs_fault_inject_hce_reset(UfsHc *u) +{ + if (u->held_req) { + u->held_req =3D NULL; + u->active_fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + u->params.fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + } else { + u->active_fault_inject_tag =3D u->params.fault_inject_tag; + } +} + +static bool ufs_fault_inject_exec_req(UfsRequest *req) +{ + UfsHc *u =3D req->hc; + + if (likely(u->active_fault_inject_tag =3D=3D UFS_FAULT_INJECT_TAG_NONE= ) || + u->held_req !=3D NULL || + req->req_upiu.header.trans_type !=3D UFS_UPIU_TRANSACTION_COMMAND)= { + return false; + } + + if (u->active_fault_inject_tag =3D=3D UFS_FAULT_INJECT_TAG_ANY) { + uint8_t op =3D req->req_upiu.sc.cdb[0]; + + if (op =3D=3D READ_10 || op =3D=3D WRITE_10) { + /* + * In 10-byte SCSI read/write commands (SBC-4), bytes 2..5 + * encode the 32-bit Logical Block Address (LBA) in + * big-endian. + */ + uint32_t lba =3D ldl_be_p(&req->req_upiu.sc.cdb[2]); + + /* + * Only intercept target I/O targeting LBA >=3D + * UFS_FAULT_INJECT_MIN_LBA. Skips guest boot-time partition + * table and superblock scanning. + */ + if (lba >=3D UFS_FAULT_INJECT_MIN_LBA) { + u->active_fault_inject_tag =3D req->req_upiu.header.task_t= ag; + u->held_req =3D req; + trace_ufs_fault_inject_hold_req( + req->req_upiu.header.task_tag, lba); + return true; + } + } + } else if (req->req_upiu.header.task_tag =3D=3D u->active_fault_inject= _tag) { + u->held_req =3D req; + trace_ufs_fault_inject_hold_req(req->req_upiu.header.task_tag, 0); + return true; + } + + return false; +} + static void ufs_hce_reset(UfsHc *u) { int i; @@ -854,6 +915,8 @@ static void ufs_hce_reset(UfsHc *u) memset(u->mcq_op_reg, 0, sizeof(u->mcq_op_reg)); } =20 + ufs_fault_inject_hce_reset(u); + u->resetting =3D false; =20 /* 5. De-assert IRQ */ @@ -2432,6 +2495,10 @@ static void ufs_exec_req(UfsRequest *req) return; } =20 + if (ufs_fault_inject_exec_req(req)) { + return; + } + switch (req->req_upiu.header.trans_type) { case UFS_UPIU_TRANSACTION_NOP_OUT: req_result =3D ufs_exec_nop_cmd(req); @@ -3058,8 +3125,166 @@ static void ufs_init_hc(UfsHc *u) =20 timer_init_ms(&u->idle_timer, QEMU_CLOCK_VIRTUAL_RT, ufs_idle_timer_cb= , u); timer_mod(&u->idle_timer, now + UFS_IDLE_TIMER_TICK); + + ufs_fault_inject_init(u); +} + +static bool ufs_fault_inject_parse_mode(const char *str, + UfsFaultInjectMode *mode, + Error **errp) +{ + if (!str || g_strcmp0(str, "abort-success") =3D=3D 0) { + *mode =3D UFS_FAULT_INJECT_ABORT_SUCCESS; + } else if (g_strcmp0(str, "abort-failed") =3D=3D 0) { + *mode =3D UFS_FAULT_INJECT_ABORT_FAILED; + } else if (g_strcmp0(str, "in-transition") =3D=3D 0) { + *mode =3D UFS_FAULT_INJECT_IN_TRANSITION; + } else if (g_strcmp0(str, "timeout") =3D=3D 0) { + *mode =3D UFS_FAULT_INJECT_TIMEOUT; + } else { + error_setg(errp, "invalid x-fault-inject-mode: %s", str); + return false; + } + return true; } =20 +static bool ufs_fault_inject_realize(UfsHc *u, Error **errp) +{ + return ufs_fault_inject_parse_mode(u->params.fault_inject_mode, + &u->fault_inject_mode, errp); +} + +static void ufs_prop_get_fault_inject_tag(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Property *prop =3D opaque; + uint32_t *ptr =3D object_field_prop_ptr(obj, prop); + UfsParams *params =3D container_of(ptr, UfsParams, fault_inject_tag); + UfsHc *u =3D container_of(params, UfsHc, params); + + visit_type_uint32(v, name, &u->active_fault_inject_tag, errp); +} + +static void ufs_prop_set_fault_inject_tag(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Property *prop =3D opaque; + uint32_t *ptr =3D object_field_prop_ptr(obj, prop); + UfsParams *params =3D container_of(ptr, UfsParams, fault_inject_tag); + UfsHc *u =3D container_of(params, UfsHc, params); + uint32_t val; + + if (!visit_type_uint32(v, name, &val, errp)) { + return; + } + + if (u->held_req !=3D NULL) { + error_setg(errp, + "cannot change %s while a request (tag %u) is held", + name, u->held_req->req_upiu.header.task_tag); + return; + } + + *ptr =3D val; + u->active_fault_inject_tag =3D val; + trace_ufs_fault_inject_set_tag(val); +} + +static void ufs_prop_set_default_fault_inject_tag(ObjectProperty *op, + const Property *prop) +{ + object_property_set_default_uint(op, prop->defval.u); +} + +const PropertyInfo ufs_prop_fault_inject_tag =3D { + .type =3D "uint32", + .description =3D "Task tag to hold for fault injection", + .get =3D ufs_prop_get_fault_inject_tag, + .set =3D ufs_prop_set_fault_inject_tag, + .set_default_value =3D ufs_prop_set_default_fault_inject_tag, + .realized_set_allowed =3D true, +}; + +static void ufs_prop_get_fault_inject_mode(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Property *prop =3D opaque; + char **ptr =3D object_field_prop_ptr(obj, prop); + UfsParams *params =3D container_of(ptr, UfsParams, fault_inject_mode); + UfsHc *u =3D container_of(params, UfsHc, params); + const char *str; + char *val; + + switch (u->fault_inject_mode) { + case UFS_FAULT_INJECT_ABORT_FAILED: + str =3D "abort-failed"; + break; + case UFS_FAULT_INJECT_IN_TRANSITION: + str =3D "in-transition"; + break; + case UFS_FAULT_INJECT_TIMEOUT: + str =3D "timeout"; + break; + case UFS_FAULT_INJECT_ABORT_SUCCESS: + default: + str =3D "abort-success"; + break; + } + + val =3D g_strdup(str); + visit_type_str(v, name, &val, errp); + g_free(val); +} + +static void ufs_prop_set_fault_inject_mode(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Property *prop =3D opaque; + char **ptr =3D object_field_prop_ptr(obj, prop); + UfsParams *params =3D container_of(ptr, UfsParams, fault_inject_mode); + UfsHc *u =3D container_of(params, UfsHc, params); + char *str; + UfsFaultInjectMode mode; + + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + if (!ufs_fault_inject_parse_mode(str, &mode, errp)) { + g_free(str); + return; + } + + g_free(*ptr); + *ptr =3D str; + u->fault_inject_mode =3D mode; + trace_ufs_fault_inject_set_mode(str); +} + +static void ufs_prop_release_fault_inject_mode(Object *obj, const char *na= me, + void *opaque) +{ + Property *prop =3D opaque; + char **ptr =3D object_field_prop_ptr(obj, prop); + + g_free(*ptr); + *ptr =3D NULL; +} + +const PropertyInfo ufs_prop_fault_inject_mode =3D { + .type =3D "str", + .description =3D "Fault injection mode: abort-success, abort-failed, " + "in-transition, timeout", + .get =3D ufs_prop_get_fault_inject_mode, + .set =3D ufs_prop_set_fault_inject_mode, + .release =3D ufs_prop_release_fault_inject_mode, + .realized_set_allowed =3D true, +}; + bool ufs_realize(UfsHc *u, DeviceState *dev, AddressSpace *dma_as, Error *= *errp) { u->dev =3D dev; @@ -3069,6 +3294,10 @@ bool ufs_realize(UfsHc *u, DeviceState *dev, Address= Space *dma_as, Error **errp) return false; } =20 + if (!ufs_fault_inject_realize(u, errp)) { + return false; + } + qbus_init(&u->bus, sizeof(UfsBus), TYPE_UFS_BUS, dev, dev->id); u->bus.hc =3D u; =20 diff --git a/hw/ufs/ufs.h b/hw/ufs/ufs.h index f6583a5db7..39213650bb 100644 --- a/hw/ufs/ufs.h +++ b/hw/ufs/ufs.h @@ -133,6 +133,53 @@ typedef struct UfsLu { UfsZoneState *zone_array; } UfsLu; =20 +/* + * Fault injection modes for x-fault-inject-mode property. + * Controls how the held transfer request and subsequent Task Management + * Request (TMR) are resolved by the controller: + * + * UFS_FAULT_INJECT_ABORT_SUCCESS: TMR ABORT_TASK aborts the held request, + * clears its state, and returns SUCCESS + * (COMPL). + * UFS_FAULT_INJECT_ABORT_FAILED: TMR ABORT_TASK returns + * TASK_MANAGEMENT_FUNC_FAILED, forcing ho= st + * driver to escalate to Host Reset. + * UFS_FAULT_INJECT_IN_TRANSITION: TMR QUERY_TASK / ABORT_TASK completes t= he + * held request successfully and returns + * COMPL (simulating a command completing = in + * transition / grace period). + * UFS_FAULT_INJECT_TIMEOUT: TMR ABORT_TASK does not complete or cle= ar + * doorbell, triggering hardware-level TMR + * timeout. + */ +typedef enum UfsFaultInjectMode { + UFS_FAULT_INJECT_ABORT_SUCCESS =3D 0, + UFS_FAULT_INJECT_ABORT_FAILED, + UFS_FAULT_INJECT_IN_TRANSITION, + UFS_FAULT_INJECT_TIMEOUT, +} UfsFaultInjectMode; + +/* + * Sentinel values for x-fault-inject-tag property. + * Task Tags in UFS are 8-bit (0..255). Values >=3D 256 are reserved as + * sentinel flags to preserve full testability of Tag 0. + * + * UFS_FAULT_INJECT_TAG_NONE: Disable fault injection (default). + * UFS_FAULT_INJECT_TAG_ANY: Automatically intercept the first user-space + * READ_10 or WRITE_10 command targeting + * LBA >=3D UFS_FAULT_INJECT_MIN_LBA. + */ +#define UFS_FAULT_INJECT_TAG_NONE 0xffffffff +#define UFS_FAULT_INJECT_TAG_ANY 0xfffffffe + +/* + * Minimum Logical Block Address (LBA) for automatic fault injection. + * Skip early disk blocks (LBA 0..511, e.g. MBR, GPT partition tables, EFI, + * and filesystem superblocks) to ensure guest OS boot-time disk discovery + * and partition scanning complete cleanly without being held. + */ +#define UFS_FAULT_INJECT_MIN_LBA 512 + typedef struct UfsParams { char *serial; uint8_t nutrs; /* Number of UTP Transfer Request Slots */ @@ -142,6 +189,8 @@ typedef struct UfsParams { uint8_t mcq_maxq; /* MCQ Maximum number of Queues */ uint32_t wb_max_size; /* WB Maximum allocation units */ uint32_t wb_min_size; /* WB Minimum allocation units */ + uint32_t fault_inject_tag; + char *fault_inject_mode; } UfsParams; =20 /* @@ -231,6 +280,11 @@ typedef struct UfsHc { uint32_t hid_fragment_count; /* Remaining fragmented 4KB units */ uint32_t hid_defrag_total; /* Requested units at defrag start */ uint32_t hid_defrag_remaining; /* Requested units left to move */ + + /* Test and fault injection properties */ + uint32_t active_fault_inject_tag; + UfsFaultInjectMode fault_inject_mode; + UfsRequest *held_req; } UfsHc; =20 static inline uint32_t ufs_mcq_sq_tail(UfsHc *u, uint32_t qid) @@ -355,4 +409,8 @@ void ufs_init_wlu(UfsLu *wlu, uint8_t wlun); bool ufs_realize(UfsHc *u, DeviceState *dev, AddressSpace *dma_as, Error **errp); void ufs_unrealize(UfsHc *u); + +extern const PropertyInfo ufs_prop_fault_inject_tag; +extern const PropertyInfo ufs_prop_fault_inject_mode; + #endif /* HW_UFS_UFS_H */ --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655211; cv=none; d=zohomail.com; s=zohoarc; b=KQ8Pg6Gm/cYxdgof6IBVVx+4k2tIcwxUv502Tvedv1kOlx/9jI+zqriqdZBFQGAgMFGrcYJ+8lXVWpog92hHUGjI98CM7hwWHo0nsUZf5LncIO+Hs2veKUVIetwyIozj3jkvlWNODyLK0DSyhsJ4lJ30TzhEwsnPYALSeVj8Cho= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655211; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=zrtx18tA7GBAcf7rkDCL5qWhALr2rFi5M+XElgsHVS0=; b=BHBGUDGFpC6cTqqL0D/Uy7DtOeQmVBzFM6HylRlY/U9KBweLSBHNWM0Lb9qLStrmx8rkmNzI2VncsHdZGzekAktJ/bN9+Hj7J4tT2JuH6g1w1Cv8LqLbgv1uxD7Zj2PHaNLEydrQaFNS1NJ1XdUiqCuLgqgh52hpACLTNlWJ8e4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792655211731962.9415664529298; Thu, 22 Oct 2026 00:46:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnUL-0007Fn-HY; Thu, 22 Oct 2026 03:45:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3D7_ZagoKClICDu75yI31E08805y.w86Ay6E-xyFy578707E.8B0@flex--stanleyjhu.bounces.google.com>) id 1xJnUJ-0007FG-Vn for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:24 -0400 Received: from mail-pl1-x647.google.com ([2607:f8b0:4864:20::647]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3D7_ZagoKClICDu75yI31E08805y.w86Ay6E-xyFy578707E.8B0@flex--stanleyjhu.bounces.google.com>) id 1xJnUI-0002Ga-7U for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:23 -0400 Received: by mail-pl1-x647.google.com with SMTP id d9443c01a7336-2e93f266d20so22825585ad.3 for ; Thu, 22 Oct 2026 00:45:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655120; x=1793259920; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=zrtx18tA7GBAcf7rkDCL5qWhALr2rFi5M+XElgsHVS0=; b=RjoVLwej0fJWvPO6vWD531FLz9RKDJFvcZbxLeqAKDg+PwO88DMZ/oT0XoosfFwjpy vCzi+BNvvKB4wVzaLBupj8POomMZE3E+azZCNC0/wkDzUNSJNeGhH+bFDZ5B0WvlDRqC HsZk5DDLBqACBFbvuiqqE1KyNZvqaQowUpBILj1kbghxXU3v2kyV98uflpycMXeoJt1z ewBWd6/g4IvvQzq98EhynyG9jwvhZBgxnzkywB2nz6mGvJlATANR6WdW9fvxjj6x7Cvo 5NngTQ9pWnU6yDDPpYBNE2qNvBvwL01LEFU3LpXNEzT6eKiT9Z+jds9hdusAc+Bw6aRs RMfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655120; x=1793259920; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=zrtx18tA7GBAcf7rkDCL5qWhALr2rFi5M+XElgsHVS0=; b=ObVxnzjI2bQ+uWQr3hPUsGozPI5ykcQOYmZ4n/4CoNCS77x6kd+SdmFLByqk2j2a+y J8xrG0FxySIizGIYLTpwrQzGThmmLFIbWyG5OztiIXDd2sZWkyaYMygVLJdpCa+mOZSo bKL3X68wuNuEocu//qRqhFICXEXrDvVWFPF4XQF2MUl6UWN68Uz63VmXXRqF0Cik0RLD PoGEPU2+GNZiYi2rRxNBq/K3hHWX+My1K3iGmUyUf3s1cUTj8b1T/aVXGNcCXFKFfUrl 27KrsMKWL36GbXGaQaqiRX8GizOAo5SPyP4Dn1Zga0QMPTIPWs+LecWbxNTfNJ4SU+fn Gmbw== X-Gm-Message-State: AFq9FYIgaLdBx7YsJ+iJJlMXmpUktu5cETeXY+qpnCVwQE/AULdOY5Y7 cm6/469KAc4OLRJNNqpW3xMDNh1SxP9bSoPZHUNzl5MiVETiJ9Ou+m8vmc4NqsfnPhzkM2ZVT7p x0238LtD8u/TU6TqimBrkSw== X-Received: from plsb13.prod.google.com ([2002:a17:902:b60d:b0:2e9:569d:e0fc]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:f645:b0:2e9:5c29:995e with SMTP id d9443c01a7336-2ea43f622fdmr37967875ad.41.1792655119529; Thu, 22 Oct 2026 00:45:19 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:07 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-3-stanleyjhu@google.com> Subject: [PATCH v2 2/8] hw/ufs: Handle task management requests for fault-injected held requests From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::647; envelope-from=3D7_ZagoKClICDu75yI31E08805y.w86Ay6E-xyFy578707E.8B0@flex--stanleyjhu.bounces.google.com; helo=mail-pl1-x647.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, T_PDS_OTHER_BAD_TLD=0.01, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655212284158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Wire up Task Management Request (TMR) and MCQ submission queue cleanup handling for transfer requests held by x-fault-inject-tag according to x-fault-inject-mode: - "abort-success": UFS_QUERY_TASK returns UFS_UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED. UFS_ABORT_TASK cancels the underlying SCSI request and marks the MCQ request in error state for SQRTC.ICU cleanup (or clears the legacy UTRL slot), then returns UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL. - "abort-failed": UFS_ABORT_TASK returns UFS_UPIU_TASK_MANAGEMENT_FUNC_FAILED while keeping the request held. - "in-transition": UFS_QUERY_TASK and UFS_ABORT_TASK complete the held transfer request with success without executing the SCSI command or transferring data, and return UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL. - "timeout": UFS_ABORT_TASK skips completion so the host driver hits its TMR timeout path. Also clear u->held_req and disarm active_fault_inject_tag when an MCQ submission queue containing the held request is cleaned up via ufs_mcq_sq_cleanup(). Signed-off-by: Stanley Jhu --- hw/ufs/ufs.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index f356818375..6d7bd16953 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -796,6 +796,91 @@ static void ufs_fault_inject_hce_reset(UfsHc *u) } } =20 +/* + * In-transition mode simulates a held request completing during TMR + * execution without executing the SCSI command or transferring data. + */ +static void ufs_fault_inject_complete_held_req(UfsRequest *hreq) +{ + uint16_t data_seg_len =3D sizeof(hreq->rsp_upiu.sr.sense_data_len); + + hreq->rsp_upiu.sr.sense_data_len =3D 0; + hreq->rsp_upiu.sr.residual_transfer_count =3D 0; + ufs_build_upiu_header(hreq, UFS_UPIU_TRANSACTION_RESPONSE, 0, + UFS_COMMAND_RESULT_SUCCESS, 0, data_seg_len); + ufs_complete_req(hreq, UFS_REQUEST_SUCCESS); +} + +static bool ufs_fault_inject_tmr(UfsHc *u, uint8_t tm_func, uint8_t lun, + uint32_t task_tag, uint8_t *tm_resp, + bool *skip_completion) +{ + UfsRequest *hreq =3D u->held_req; + + *skip_completion =3D false; + if (!hreq || task_tag !=3D u->active_fault_inject_tag || + hreq->req_upiu.header.lun !=3D lun) { + return false; + } + + if (tm_func =3D=3D UFS_QUERY_TASK) { + if (u->fault_inject_mode =3D=3D UFS_FAULT_INJECT_IN_TRANSITION) { + u->held_req =3D NULL; + u->active_fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + u->params.fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + *tm_resp =3D UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL; + ufs_fault_inject_complete_held_req(hreq); + } else { + *tm_resp =3D UFS_UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED; + } + return true; + } + + if (tm_func =3D=3D UFS_ABORT_TASK) { + if (u->fault_inject_mode =3D=3D UFS_FAULT_INJECT_ABORT_FAILED) { + *tm_resp =3D UFS_UPIU_TASK_MANAGEMENT_FUNC_FAILED; + } else if (u->fault_inject_mode =3D=3D UFS_FAULT_INJECT_TIMEOUT) { + *skip_completion =3D true; + } else if (u->fault_inject_mode =3D=3D UFS_FAULT_INJECT_IN_TRANSIT= ION) { + u->held_req =3D NULL; + u->active_fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + u->params.fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + *tm_resp =3D UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL; + ufs_fault_inject_complete_held_req(hreq); + } else { + /* UFS_FAULT_INJECT_ABORT_SUCCESS or default */ + u->held_req =3D NULL; + if (ufs_mcq_req(hreq)) { + if (hreq->sreq !=3D NULL) { + SCSIRequest *sreq =3D hreq->sreq; + hreq->sreq =3D NULL; + scsi_req_cancel(sreq); + } + hreq->state =3D UFS_REQUEST_ERROR; + } else { + ufs_clear_req(hreq); + hreq->state =3D UFS_REQUEST_IDLE; + u->reg.utrldbr &=3D ~(1 << hreq->slot); + } + u->active_fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + u->params.fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + *tm_resp =3D UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL; + } + return true; + } + + return false; +} + +static void ufs_fault_inject_sq_cleanup(UfsHc *u, UfsRequest *req) +{ + if (u->held_req =3D=3D req) { + u->held_req =3D NULL; + u->active_fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + u->params.fault_inject_tag =3D UFS_FAULT_INJECT_TAG_NONE; + } +} + static bool ufs_fault_inject_exec_req(UfsRequest *req) { UfsHc *u =3D req->hc; @@ -968,6 +1053,7 @@ static void ufs_process_tmr(UfsHc *u, uint32_t val) UtpTaskReqDesc desc; uint8_t tm_func, tm_resp, lun; uint32_t task_tag; + bool skip_completion =3D false; =20 if (ufs_addr_read(u, desc_addr, &desc, sizeof(desc))) { continue; @@ -977,7 +1063,12 @@ static void ufs_process_tmr(UfsHc *u, uint32_t val) lun =3D desc.upiu_req.req_header.lun; task_tag =3D be32_to_cpu(desc.upiu_req.input_param2); =20 - if (tm_func =3D=3D UFS_QUERY_TASK) { + if (ufs_fault_inject_tmr(u, tm_func, lun, task_tag, &tm_resp, + &skip_completion)) { + if (skip_completion) { + continue; + } + } else if (tm_func =3D=3D UFS_QUERY_TASK) { UfsRequest *req =3D ufs_find_req_by_tag(u, lun, task_tag); =20 if (req) { @@ -1245,6 +1336,7 @@ static void ufs_mcq_sq_cleanup(UfsHc *u, uint8_t qid) } =20 if (req) { + ufs_fault_inject_sq_cleanup(u, req); if (req->sreq !=3D NULL) { SCSIRequest *sreq =3D req->sreq; req->sreq =3D NULL; --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655229; cv=none; d=zohomail.com; s=zohoarc; b=kw/TGabOx0VmngdMqvQKeFlRxyOkvc6bMqs52kv+JYYel9jv6C9qjT6ttVGLZCrRBVBOQQhVt9vEbDbHWVaSxx8SahvDT/lln7Tz6rsfxWdP1T8GHm9gA2C8IwKgpepIsrcMmzZJbp3hILJyQcPfima1YdIGFDGWc4/MbYA6/QQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655229; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=SihwI6II02J0wSv5mm6TKsCxV9e6o3CfwSzvMI5XV88=; b=LNW4oXaATEY+6t8tjWhHcCE/Yi1ZoBthKpcMsgUEoMequB8v8ZShL/0ovGr1V7QVcUVEmz/BnDKWDn1IF2FtqqHB/T46y4bdV/xCG6oTKLyRO/LdG9DON0Uoh3AWjVAPLBXl8XlMVdUqUb1rkUNYfPtUhQUx5aC+uzjjCieJzdo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792655228998212.16677657734806; Thu, 22 Oct 2026 00:47:08 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnVw-0000G3-JW; Thu, 22 Oct 2026 03:47:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3Eb_ZagoKClQEFw970K53G2AA270.yA8C08G-z0H079A929G.AD2@flex--stanleyjhu.bounces.google.com>) id 1xJnV6-0007bm-Rp for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:46:32 -0400 Received: from mail-pj1-x1047.google.com ([2607:f8b0:4864:20::1047]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3Eb_ZagoKClQEFw970K53G2AA270.yA8C08G-z0H079A929G.AD2@flex--stanleyjhu.bounces.google.com>) id 1xJnV4-0002WA-Qr for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:46:12 -0400 Received: by mail-pj1-x1047.google.com with SMTP id 98e67ed59e1d1-3ad53f538d2so1640749a91.3 for ; Thu, 22 Oct 2026 00:46:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655165; x=1793259965; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=SihwI6II02J0wSv5mm6TKsCxV9e6o3CfwSzvMI5XV88=; b=i+m4/7XXzTNDHETjEfm5wwwAiPElfbW5u/fkpEihsuBICRz2dwNQKuYQN78xu2u2ll TiZoP70oUa+SujY9vf9UvfeduDL7G9Mjo5BfEI1319kv5AsTcAkPsFDQyu6YcZP079DC 22Bp765Z+L2qky+ow1MoOfSxKVfNkRleK7p14lHqbJg1k0jogr0u1O77dxBLvee4nVVM QmDhHfcJt73EHmS6lzmVzDrHypbr1ZdsvUuCJ1UqiagCjxQ+46fJwihDmOWCqRMMswUK 1TL9E6iDjES9DYq1OH7GQISYX6t79YT5geMWfHdBXTaE9AsBETOr/Xz7lfkIBkKrvse4 3rwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655165; x=1793259965; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=SihwI6II02J0wSv5mm6TKsCxV9e6o3CfwSzvMI5XV88=; b=aC61Ef3EgmB0DXNr65DLYG5+Ettrp2bDyEDukihoAn1Z4hNPR0Z+4fny685t5fhe2B e5FMOFrtqYncmTFpq7SdcjRdHe7Xu6IcK/N31dcbJ7uJJTTZvGlziWB0aFrvUF9LEsVy vAL4IOLN9sF0xbBczSrmh6q/sj3ZVcFGqycbX0uTLDtBPf+xmHpNBPO1L4mrw+WQ4atF OmsC8Aieiz10HFQyrPLnCvikM6vuE+B8p7sv4d/tH1OH2WWLpfaa0ZOzNwwbwGJjmq3/ zIBL4vNDkBuMUS6apidxu5n2wPyGjfjfxkasht00/yyIMaHxbPgIuWQnFWBqM7dXPYQy 7tag== X-Gm-Message-State: AFq9FYL12TU29x47v1cdkepDtJrp6K6RcpomW6zMX+KIZlIySZfJqgc3 Hv72BchjI2mpYjDrGQwCJPo3v4yUg8Q1fIyCQ0rzSY17WXFRAiSbRV8yOz+y8nouWp8682+pano OH+10+Ehdj+5a/XTcNSYjYQ== X-Received: from pjhr3.prod.google.com ([2002:a17:90a:5003:b0:3a9:ccc3:cbae]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4b0a:b0:3a2:b16d:928b with SMTP id 98e67ed59e1d1-3ad86caa7cdmr3724017a91.46.1792655121455; Thu, 22 Oct 2026 00:45:21 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:08 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-4-stanleyjhu@google.com> Subject: [PATCH v2 3/8] hw/ufs: Add ssu-timeout mode for power management recovery testing From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1047; envelope-from=3Eb_ZagoKClQEFw970K53G2AA270.yA8C08G-z0H079A929G.AD2@flex--stanleyjhu.bounces.google.com; helo=mail-pj1-x1047.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655230689158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the experimental fault injection property x-fault-inject-mode with a new "ssu-timeout" mode to facilitate automated testing of host driver power management and Start Stop Unit (SSU) recovery handling. When x-fault-inject-mode=3D"ssu-timeout" is set and x-fault-inject-tag is armed (e.g., 0xfffffffe for any tag, or a matching tag), the controller only intercepts SCSI START_STOP (0x1B) commands sent to the UFS Device Well-Known LUN (WLUN) and holds them without queuing them to the SCSI layer, while letting non-SSU commands complete normally. This triggers the host driver's 10-second SSU command timeout and subsequent power management recovery routines (e.g., during suspend-to-idle or freeze transitions), verifying host error recovery and link restoration paths. Signed-off-by: Stanley Jhu --- hw/ufs/ufs.c | 24 +++++++++++++++++++++--- hw/ufs/ufs.h | 4 ++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index 6d7bd16953..c54b31716e 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -884,6 +884,7 @@ static void ufs_fault_inject_sq_cleanup(UfsHc *u, UfsRe= quest *req) static bool ufs_fault_inject_exec_req(UfsRequest *req) { UfsHc *u =3D req->hc; + uint8_t op; =20 if (likely(u->active_fault_inject_tag =3D=3D UFS_FAULT_INJECT_TAG_NONE= ) || u->held_req !=3D NULL || @@ -891,9 +892,21 @@ static bool ufs_fault_inject_exec_req(UfsRequest *req) return false; } =20 - if (u->active_fault_inject_tag =3D=3D UFS_FAULT_INJECT_TAG_ANY) { - uint8_t op =3D req->req_upiu.sc.cdb[0]; + op =3D req->req_upiu.sc.cdb[0]; + if (u->fault_inject_mode =3D=3D UFS_FAULT_INJECT_SSU_TIMEOUT) { + if (op =3D=3D START_STOP && + req->req_upiu.header.lun =3D=3D UFS_UPIU_UFS_DEVICE_WLUN && + (u->active_fault_inject_tag =3D=3D UFS_FAULT_INJECT_TAG_ANY || + req->req_upiu.header.task_tag =3D=3D u->active_fault_inject_t= ag)) { + u->active_fault_inject_tag =3D req->req_upiu.header.task_tag; + u->held_req =3D req; + trace_ufs_fault_inject_hold_req(req->req_upiu.header.task_tag,= 0); + return true; + } + return false; + } =20 + if (u->active_fault_inject_tag =3D=3D UFS_FAULT_INJECT_TAG_ANY) { if (op =3D=3D READ_10 || op =3D=3D WRITE_10) { /* * In 10-byte SCSI read/write commands (SBC-4), bytes 2..5 @@ -3233,6 +3246,8 @@ static bool ufs_fault_inject_parse_mode(const char *s= tr, *mode =3D UFS_FAULT_INJECT_IN_TRANSITION; } else if (g_strcmp0(str, "timeout") =3D=3D 0) { *mode =3D UFS_FAULT_INJECT_TIMEOUT; + } else if (g_strcmp0(str, "ssu-timeout") =3D=3D 0) { + *mode =3D UFS_FAULT_INJECT_SSU_TIMEOUT; } else { error_setg(errp, "invalid x-fault-inject-mode: %s", str); return false; @@ -3320,6 +3335,9 @@ static void ufs_prop_get_fault_inject_mode(Object *ob= j, Visitor *v, case UFS_FAULT_INJECT_TIMEOUT: str =3D "timeout"; break; + case UFS_FAULT_INJECT_SSU_TIMEOUT: + str =3D "ssu-timeout"; + break; case UFS_FAULT_INJECT_ABORT_SUCCESS: default: str =3D "abort-success"; @@ -3370,7 +3388,7 @@ static void ufs_prop_release_fault_inject_mode(Object= *obj, const char *name, const PropertyInfo ufs_prop_fault_inject_mode =3D { .type =3D "str", .description =3D "Fault injection mode: abort-success, abort-failed, " - "in-transition, timeout", + "in-transition, timeout, ssu-timeout", .get =3D ufs_prop_get_fault_inject_mode, .set =3D ufs_prop_set_fault_inject_mode, .release =3D ufs_prop_release_fault_inject_mode, diff --git a/hw/ufs/ufs.h b/hw/ufs/ufs.h index 39213650bb..29332e6b1d 100644 --- a/hw/ufs/ufs.h +++ b/hw/ufs/ufs.h @@ -151,12 +151,16 @@ typedef struct UfsLu { * UFS_FAULT_INJECT_TIMEOUT: TMR ABORT_TASK does not complete or cle= ar * doorbell, triggering hardware-level TMR * timeout. + * UFS_FAULT_INJECT_SSU_TIMEOUT: Intercepts SCSI START_STOP (0x1B) comma= nds + * targeting the UFS Device WLUN when + * x-fault-inject-tag is armed. */ typedef enum UfsFaultInjectMode { UFS_FAULT_INJECT_ABORT_SUCCESS =3D 0, UFS_FAULT_INJECT_ABORT_FAILED, UFS_FAULT_INJECT_IN_TRANSITION, UFS_FAULT_INJECT_TIMEOUT, + UFS_FAULT_INJECT_SSU_TIMEOUT, } UfsFaultInjectMode; =20 /* --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655211; cv=none; d=zohomail.com; s=zohoarc; b=FFz1/5YxL5ij8K+aO51SeWEEN7otwEvyuzFo1mEY6Y2PizF2S7ALZFMRF+az6+OUb118gzqpthoSaSZWiZjba5thHoNQds3RcRTwWFa+f7xUZqgVBzUGl8nkMw9nUeDFWPgM5Nv3Sr3tYdEnTs5ZYbVz+Us9abT4OHTxiQuMm3c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655211; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=JErEDf1V1JkwNyPIaYWtSeaKHe2MEITTzSoWnSSXLZc=; b=kCoTp7VBgmBkYJ+1j4B+FN8I3j6LWBo6c/SA/sBbQqJnTzx3BeHbeijKhTPB3bcoUbDSy+FnQw47Qu057d460nAaBG1hCK/INrQtVWzYI85YuGvnxXVqV1x5vrEG5TZ+UsfcIuZqH8ZJXLTi2G0YUld5tQ9X7OcB2gHbXdgnctU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 179265521175929.134175825206057; Thu, 22 Oct 2026 00:46:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnUT-0007H9-OV; Thu, 22 Oct 2026 03:45:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3GL_ZagoKClsLM3GE7RCAN9HH9E7.5HFJ7FN-67O7EGHG9GN.HK9@flex--stanleyjhu.bounces.google.com>) id 1xJnUS-0007Ga-FO for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:32 -0400 Received: from mail-pf1-x446.google.com ([2607:f8b0:4864:20::446]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3GL_ZagoKClsLM3GE7RCAN9HH9E7.5HFJ7FN-67O7EGHG9GN.HK9@flex--stanleyjhu.bounces.google.com>) id 1xJnUQ-0002HK-Lv for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:32 -0400 Received: by mail-pf1-x446.google.com with SMTP id d2e1a72fcca58-89e96c03cd0so1214188b3a.1 for ; Thu, 22 Oct 2026 00:45:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655129; x=1793259929; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=JErEDf1V1JkwNyPIaYWtSeaKHe2MEITTzSoWnSSXLZc=; b=wjKUkXFEW59YEjQSxs2prFAbhqAwuoHL3J5t6QdSe084G43Q0yN5JSbHq785XViPJo C6bgEI7BlIx0k7B/DgAnBV3tOHdg2CVgUxCb8VQTKWXKvXPP4slTn6te9sYnXNpHquM3 XRopY7SQmzwDVVLE4HF7hRk2++XMWi1HrA+q77z/a2NEAXmmCvK4hSDGbWzOpf12W7uM fxvdnJG5WKKuwxKnTmV833WpP/J1tmwX9BqiI5l49XYXV6Vrp3KdfC+wbY5ruDLds/Oe tFna7+o7Dyl1K1pfjR5epmFTNZYuUq/BX5R9HlqotCCDLHLcsfS4uX3KEdqTZE7mCLd9 HCaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655129; x=1793259929; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=JErEDf1V1JkwNyPIaYWtSeaKHe2MEITTzSoWnSSXLZc=; b=Plddh2HpS16Mz+yVkA5FRsPLIovo80SAiM62q3Mwa5kzgP2g65hEOgUuIvtwYhYiuA 2uzjqYRnIS0ulhyGGJZJb2uZX+e9JnFw8sCRPYmtkjM4JkVCiTBkjVliK341VBPgVhj+ B12UjXJoMV+67tbKXPRvo0Yxcu+EPJP2S2eMhNI03ksjcg+3Pox/7HWCdZzz3/LV7pWx JXeKJ8iOfHx368sOt7zxyeLS/50XLrrhJwC+yf05KQVs2X0BDT5L0FMWEhlDvW5UDwVz AHZbsZJAaljkCZo6Qyg6m2tMxb+LiTAUV0YhBR+SLEqDlWg+RGbFf36l0agdIy7cju4M AhLQ== X-Gm-Message-State: AFq9FYKyqdPUkCfnSfduS4jJe9Yb+20wqfPIG5y3ep1EgzMz4+2wqDuj JxtHjg76tvOjc03pYzaAIeO2mV0YV+RgNDNB0q5pNmTmu45R21/OzlxaOMB+AWG/4oxCOyBL2ds jbUOQ0q2qvfMY+P8SIKwn1A== X-Received: from pfav10.prod.google.com ([2002:a05:6a00:ab0a:b0:88c:e369:e5a4]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2d90:b0:87c:e44e:5694 with SMTP id d2e1a72fcca58-8a089d0d36amr3427738b3a.21.1792655128773; Thu, 22 Oct 2026 00:45:28 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:09 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-5-stanleyjhu@google.com> Subject: [PATCH v2 4/8] docs/system/ufs: Update task management request support status From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::446; envelope-from=3GL_ZagoKClsLM3GE7RCAN9HH9E7.5HFJ7FN-67O7EGHG9GN.HK9@flex--stanleyjhu.bounces.google.com; helo=mail-pf1-x446.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655212312158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The task management request (TMR) handling implemented for UFS supports QUERY TASK and ABORT TASK, while other task management functions return TASK MANAGEMENT FUNCTION NOT SUPPORTED. Update the documentation in ufs.rst to reflect the current implementation by removing the outdated note under nutmrs and updating the Limitations section accordingly. Signed-off-by: Stanley Jhu --- docs/system/devices/ufs.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/system/devices/ufs.rst b/docs/system/devices/ufs.rst index a76fdbe76e..36f5b958cf 100644 --- a/docs/system/devices/ufs.rst +++ b/docs/system/devices/ufs.rst @@ -51,7 +51,6 @@ Host Controller Properties =20 ``nutmrs`` (default 8, maximum 8) Number of UTP task management request slots advertised to the guest. - Task management requests are not processed yet (see Limitations). =20 ``mcq`` (default off) Advertise Multi-Circular Queue (MCQ) support. When off, the guest @@ -136,8 +135,10 @@ Limitations link startup, DME attribute access and hibernation are handled; DME reads return fixed values, and DME writes, power mode changes and hibernation do not change any link state. -* UTP task management requests are not processed, so a guest that - tries to abort a command or reset a logical unit gets no completion. +* Only the ``QUERY TASK`` and ``ABORT TASK`` UTP task management + requests are supported; other task management functions such as + ``LOGICAL UNIT RESET`` return ``TASK MANAGEMENT FUNCTION NOT + SUPPORTED``. * The Boot and RPMB well-known logical units only answer basic SCSI commands such as INQUIRY; boot and RPMB data access are not emulated. * The device cannot be migrated. --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655198; cv=none; d=zohomail.com; s=zohoarc; b=buOqaNbxQ2PEJCmDLIilPM/JGyNcf8O/d9b3vbSgBVA46ctUAHNSl63QIbTSGMhDUzRkoWyBjgOnyFZIwdwvLeqwf1iDtzl2kcElJyOdYo1wTVfev3lqC6/mKkFpLNJMG2adnL/4OiSH73AnL73B00hmDgoOjmR9OEgcBb8tSLg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655198; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=QW4je3U/3zyQLhRvG412cMinFBcQ+6FyWD2o0c1N0B0=; b=UNM32pTl/0jX5JfDSxFGlvhvGCxRWuq8CNle09RTt/RKcevIifs4sJ9g4Jalur2ztM5V4Y3oLHIXvhGWkM0Nh/e98l3DG3rejoJc+S1s2x8ah2tPaBaFikss3F0OVp0j5BbGex+CdG17tgNXwrDRcs0YM+oX+R0RWXJT+2bz0Uw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792655198616119.67804623342329; Thu, 22 Oct 2026 00:46:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnUX-0007Jy-QV; Thu, 22 Oct 2026 03:45:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3Gr_ZagoKCl0NO5IG9TECPBJJBG9.7JHL9HP-89Q9GIJIBIP.JMB@flex--stanleyjhu.bounces.google.com>) id 1xJnUU-0007IQ-Pt for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:34 -0400 Received: from mail-pg1-x545.google.com ([2607:f8b0:4864:20::545]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3Gr_ZagoKCl0NO5IG9TECPBJJBG9.7JHL9HP-89Q9GIJIBIP.JMB@flex--stanleyjhu.bounces.google.com>) id 1xJnUT-0002Hq-1O for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:34 -0400 Received: by mail-pg1-x545.google.com with SMTP id 41be03b00d2f7-cd3b9e70f88so1746245a12.0 for ; Thu, 22 Oct 2026 00:45:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655131; x=1793259931; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=QW4je3U/3zyQLhRvG412cMinFBcQ+6FyWD2o0c1N0B0=; b=h0B/+eLKMlPWnw+ynpgDxmMu4lf6ZMF/BhuokrWAErzG2GxbTPxOyxDmDEmNpbS+jS MtAdgyXAjyXR+aYdEHspc1DJakkE60zRhwgtqX9tfGP3LE99LggE+m5AdSX3YRBGclF0 B5w6pIicqlm4eLVP9gns1buEwrb4ag1ICuC2TD5VmdnFB6uovx8KOU+Lr60D3spq97AL SVyiVXhyg1SV8MntwkpFZgu24nj97D55XdQ/J4Tnl6ImxvlD7zF9bvHKzHWpmsyQcek4 cPdkwDJqQQapyk3XBFUvCgqqKOb25IMufbNKAgXr/0Kcfbi25cfWAJh46zkBGWrXT3nU 5JZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655131; x=1793259931; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=QW4je3U/3zyQLhRvG412cMinFBcQ+6FyWD2o0c1N0B0=; b=eAhlEd+AeDzhfsGDDMkflayuhcHOKzK0rKksw2yEWs8OwQuhcb9z6ok3GpxSVXPE09 HKJ4EEp4NutJwvmUPP2Ar+xyz6NDI7806SZ7HmD5QxB7U7J+og8RboARS6PEEhbrSr88 LvAl1dkIwZTsnyRnOTIj51sw4QghH/+xeHJxNr8cdzcjbgF2RzB3ECPkT2XdYr3LlWm1 Cj04DUFQlFDpa6ZIBLCSaatjtd23pBEaLF9Ne1GYIXxn/BRb4kUJwT5E9kpaG0JXQFwr HF9wsGAIHov/QlDys5VTb+5qxZcuVDm0R4qPi7uoOiz44VzrmfW9cJIl7IeOa+rm9a8M U2Jw== X-Gm-Message-State: AFq9FYIFiJwnpn5tyVfmKQlvi4bx9+h5WVRW/N2leNP+ssggvOMhZrVU R5yVZOJDigUVnsilC+NqUJ68edYmAKe6a/ojlyYkYoN7t1c0MXHDPER2VegkoV7NfbkAUvbvm0c rOYqz8R9t6a0YA6M8/D7wKA== X-Received: from pgdu13.prod.google.com ([2002:a05:6a02:2f4d:b0:cc9:5e28:9460]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:918a:b0:3e1:a769:9620 with SMTP id adf61e73a8af0-3e287f3c888mr3850796637.71.1792655130904; Thu, 22 Oct 2026 00:45:30 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:10 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-6-stanleyjhu@google.com> Subject: [PATCH v2 5/8] tests/qtest/ufs-test: Add TMR and async MCQ SCSI submission helpers From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::545; envelope-from=3Gr_ZagoKCl0NO5IG9TECPBJJBG9.7JHL9HP-89Q9GIJIBIP.JMB@flex--stanleyjhu.bounces.google.com; helo=mail-pg1-x545.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655200091158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add ufs_send_tmr() and ufs_mcq_send_scsi_cmd_async() helper functions in preparation for UTMRL task management and QOM fault injection unit tests. Signed-off-by: Stanley Jhu --- tests/qtest/ufs-test.c | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c index e24caa2efc..f577fe2614 100644 --- a/tests/qtest/ufs-test.c +++ b/tests/qtest/ufs-test.c @@ -1899,6 +1899,59 @@ static void ufstest_hid(void *obj, void *data, QGues= tAllocator *alloc) ufs_exit(ufs, alloc); } =20 +static G_GNUC_UNUSED void ufs_send_tmr(QUfs *ufs, uint64_t utmrlba, int sl= ot, + uint8_t tm_func, uint8_t lun, + uint32_t task_tag, + UtpTaskReqDesc *utrd_out) +{ + uint64_t desc_addr =3D utmrlba + slot * sizeof(UtpTaskReqDesc); + UtpTaskReqDesc desc =3D { 0 }; + + desc.header.dword_0 =3D cpu_to_le32(UFS_UTP_REQ_DESC_INT_CMD); + desc.header.dword_2 =3D cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS); + + desc.upiu_req.req_header.trans_type =3D UFS_UPIU_TRANSACTION_TASK_REQ; + desc.upiu_req.req_header.query_func =3D tm_func; + desc.upiu_req.req_header.lun =3D lun; + desc.upiu_req.req_header.task_tag =3D 0x10 + slot; + desc.upiu_req.input_param1 =3D cpu_to_be32(lun); + desc.upiu_req.input_param2 =3D cpu_to_be32(task_tag); + + qtest_memwrite(ufs->dev.bus->qts, desc_addr, &desc, sizeof(desc)); + + ufs_wreg(ufs, A_UTMRLDBR, 1 << slot); + ufs_wait_for_irq(ufs); + g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTMRCS)); + ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTMRCS, 1)); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLDBR) & (1 << slot), =3D=3D, 0); + + qtest_memread(ufs->dev.bus->qts, desc_addr, utrd_out, sizeof(*utrd_out= )); +} + +static G_GNUC_UNUSED int ufs_mcq_send_scsi_cmd_async(QUfs *ufs, uint8_t lu= n, + const uint8_t *cdb) +{ + int cmd_desc_slot =3D alloc_cmd_desc_slot(ufs); + uint64_t req_upiu_addr =3D + ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE; + UtpUpiuReq req_upiu =3D { 0 }; + UtpTransferReqDesc utrd; + + req_upiu.header.trans_type =3D UFS_UPIU_TRANSACTION_COMMAND; + req_upiu.header.flags =3D UFS_UPIU_CMD_FLAGS_NONE; + req_upiu.header.lun =3D lun; + req_upiu.header.task_tag =3D cmd_desc_slot; + memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE); + qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu, + sizeof(req_upiu)); + + utrd =3D ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0= ); + __ufs_send_transfer_request_mcq_async(ufs, lun, &utrd); + + return cmd_desc_slot; +} + + #define ZONE_SIZE (2 * 1024 * 1024) #define ZONE_BLOCKS (ZONE_SIZE / 4096) #define MAX_OPEN_ZONE 6 --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655213; cv=none; d=zohomail.com; s=zohoarc; b=Jf03nyG1nmAx6cEFyOVsirGexRkzwfmQkCx37IUjGLy7S6Z6ho62DNfDBHlisCRXSOkDS1NpvP9FNvT+WDZ/Ok0c3KEL6QwMhUwcD5K3wkCmW4tQyy0IRz4c8LrO5Kam0RVP9edYgVZhd8nZQAMAGpmIQJHA8IdQeRpD+Gqe3Lw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655213; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jDiCW1Z8nBWLuyV93omuB93zBx5tYJkLyAUuU4CEhy4=; b=n88c2YzcbPhvXvqPuaB3EpxAt+TKgRdfgmhN5H7J2oHt/4bRTf8QPpWW8iB5OnLxmu0+cWyyyXnbClh7AnPtGsatD5GTAxXHeFQW5NIwvg9JU0TE/qMNxn59tMaNRwdkz1HFFGVc2tFgKaEbwAYgjKP/kWoEGnjlFDF3JC8Q6dc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792655213737753.3637958785804; Thu, 22 Oct 2026 00:46:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnVV-0007bg-M2; Thu, 22 Oct 2026 03:46:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3HL_ZagoKCl8PQ7KIBVGERDLLDIB.9LJNBJR-ABSBIKLKDKR.LOD@flex--stanleyjhu.bounces.google.com>) id 1xJnUX-0007Or-Us for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:37 -0400 Received: from mail-pg1-x546.google.com ([2607:f8b0:4864:20::546]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3HL_ZagoKCl8PQ7KIBVGERDLLDIB.9LJNBJR-ABSBIKLKDKR.LOD@flex--stanleyjhu.bounces.google.com>) id 1xJnUU-0002IO-QD for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:36 -0400 Received: by mail-pg1-x546.google.com with SMTP id 41be03b00d2f7-cd3b9e70f88so1746277a12.0 for ; Thu, 22 Oct 2026 00:45:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655133; x=1793259933; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=jDiCW1Z8nBWLuyV93omuB93zBx5tYJkLyAUuU4CEhy4=; b=p4Y8aEadFEHSyGu2dEQ4KwhXk1pf/8sViNZemjiDXr4PxMaxW1jwAXtcCjlnjhojwt s3ReiVjMyKrjBGh8c/cI8ABAXyWKPK/yeHL9m+rzOc6UX/gqdem3PYHETszBi1pvuVGE dlq0iWw/yop4fyO+hJq3FkNjkStYToaqRlO3AochfBQwKv69BRLXMbSaTmaROdyVDlLo Jp+O2hfeI+HEx5ln/RvRNBg5bJTydE5Hj7ZaK0CzF8vh7tV1iSubkuK2uXTHqih8Fpi/ cnAZT6SU3k9TSafEHDqWgAo1+gbiljSHtnY1buqLuRHb39Uh1Hdau7KyywuE9aQcKrrD F0RQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655133; x=1793259933; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=jDiCW1Z8nBWLuyV93omuB93zBx5tYJkLyAUuU4CEhy4=; b=sAMJA1HhyJ94ObjRdfKzUago2lLxiudcX5GAX5wAen37KZNzMvF7jWnFhsSCFLBfcD akG3Uoy8VqeY8W9QBnO2CYzRaXLWHGXqncPQzOKgMm6LjQThA39yiMFtfpr0q22MhiHb 8geQ3ZgoZtbtOtXSx/VgvsK5GNL2HF/P9Djwjd529GbCkBYMZarNy2KX5j3Hws9+QKYx kEsnI0njdT84iYZofyYXKSle8Rtrr22zFbUbbYio9MZLv6diBaJdaklEVkM9UbT0x2Ie IIOEhkUR2PwOnL3tT6uTW8ve7fHTiVR2mwAhGt5ALvVG8e7AsaMtdUzSiGFKcZiOtsdM wFQA== X-Gm-Message-State: AFq9FYKgl7ZVwOv3XqxoxTvzb0o+o6xj7z0Q/I4LIgKUb2GW3Oq/N+VM 4MFGbgmES814w1E/+W2IURt6YR7f2slJex068EwbHrWG/YHcKUFMO4v82Z8FKhhKL5Hl29VJ079 yGtufojx4QbFwc+5+GjMwlQ== X-Received: from pfay28.prod.google.com ([2002:a05:6a00:181c:b0:885:756d:3709]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:828c:b0:3e2:30c1:fe01 with SMTP id adf61e73a8af0-3e287f3212fmr3637108637.69.1792655132738; Thu, 22 Oct 2026 00:45:32 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:11 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-7-stanleyjhu@google.com> Subject: [PATCH v2 6/8] tests/qtest/ufs-test: Add HCE reset unit test From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::546; envelope-from=3HL_ZagoKCl8PQ7KIBVGERDLLDIB.9LJNBJR-ABSBIKLKDKR.LOD@flex--stanleyjhu.bounces.google.com; helo=mail-pg1-x546.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655214499158501 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add ufs_test_hce_reset() to verify HCE 1->0->1 controller reset behavior, checking that UTMRLRSR and dynamic MCQ queue configuration and operational registers reset to 0 while host-configured registers (IE, UTMRLBA/UTMRLBAU, MCQCONFIG) and static capability offsets (SQDAO/CQDAO) are preserved and subsequent I/O succeeds. Signed-off-by: Stanley Jhu --- tests/qtest/ufs-test.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c index f577fe2614..019107d818 100644 --- a/tests/qtest/ufs-test.c +++ b/tests/qtest/ufs-test.c @@ -1952,6 +1952,80 @@ static G_GNUC_UNUSED int ufs_mcq_send_scsi_cmd_async= (QUfs *ufs, uint8_t lun, } =20 =20 +static void ufs_test_hce_reset(void *obj, void *data, QGuestAllocator *all= oc) +{ + QUfs *ufs =3D obj; + uint32_t mcqcap, qcfgptr, mcq_reg_offset; + uint32_t orig_sqdao, orig_cqdao, orig_ie; + enum UtpOcsCodes ocs; + UtpUpiuRsp rsp_upiu; + + ufs_init(ufs, alloc); + g_assert_true(ufs->support_mcq); + + mcqcap =3D ufs_rreg(ufs, A_MCQCAP); + qcfgptr =3D FIELD_EX32(mcqcap, MCQCAP, QCFGPTR); + mcq_reg_offset =3D qcfgptr * 0x200 + TEST_QID * 0x40; + + orig_sqdao =3D ufs_rreg(ufs, mcq_reg_offset + A_SQDAO); + orig_cqdao =3D ufs_rreg(ufs, mcq_reg_offset + A_CQDAO); + orig_ie =3D ufs_rreg(ufs, A_IE); + g_assert_cmpuint(orig_sqdao, !=3D, 0); + g_assert_cmpuint(orig_cqdao, !=3D, 0); + g_assert_cmpuint(orig_ie, !=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_SQATTR), !=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_CQATTR), !=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, orig_sqdao + 0x4), !=3D, 0); + + ufs_wreg(ufs, A_UTMRLBA, 0x1000); + ufs_wreg(ufs, A_UTMRLBAU, 0x1); + ufs_wreg(ufs, A_UTMRLRSR, 1); + ufs_wreg(ufs, A_MCQCONFIG, 0x100); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLRSR), =3D=3D, 1); + + /* Write HCE=3D0 to trigger controller reset */ + ufs_wreg(ufs, A_HCE, 0); + g_assert_cmpuint(FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE), =3D=3D, 0= ); + g_assert_cmpuint(ufs_rreg(ufs, A_HCS), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLRSR), =3D=3D, 0); + + /* Verify host-configured registers remain preserved across HCE=3D0 */ + g_assert_cmpuint(ufs_rreg(ufs, A_IE), =3D=3D, orig_ie); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLBA), =3D=3D, 0x1000); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLBAU), =3D=3D, 0x1); + g_assert_cmpuint(ufs_rreg(ufs, A_MCQCONFIG), =3D=3D, 0x100); + + /* Verify dynamic queue configuration registers reset to 0 */ + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_SQATTR), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_SQLBA), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_CQATTR), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_CQLBA), =3D=3D, 0); + + /* Verify dynamic MCQ operational registers reset to 0 on HCE=3D0 */ + g_assert_cmpuint(ufs_rreg(ufs, orig_sqdao), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, orig_sqdao + 0x4), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, orig_cqdao), =3D=3D, 0); + g_assert_cmpuint(ufs_rreg(ufs, orig_cqdao + 0x4), =3D=3D, 0); + + /* Verify read-only capability offsets (SQDAO/CQDAO) remain intact */ + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_SQDAO), =3D=3D, orig= _sqdao); + g_assert_cmpuint(ufs_rreg(ufs, mcq_reg_offset + A_CQDAO), =3D=3D, orig= _cqdao); + + /* Re-enable HCE=3D1 and verify dynamic queue status/pointers remain 0= */ + ufs_wreg(ufs, A_HCE, FIELD_DP32(0, HCE, HCE, 1)); + g_assert_cmpuint(FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE), =3D=3D, 1= ); + + /* Free previous guest allocations before re-initializing */ + ufs_exit(ufs, alloc); + + /* Re-enable HCE=3D1, re-init controller, and verify normal I/O succee= ds */ + ufs_init(ufs, alloc); + ocs =3D ufs_send_nop_out(ufs, &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + + ufs_exit(ufs, alloc); +} + #define ZONE_SIZE (2 * 1024 * 1024) #define ZONE_BLOCKS (ZONE_SIZE / 4096) #define MAX_OPEN_ZONE 6 @@ -3130,6 +3204,7 @@ static void ufs_register_nodes(void) &io_test_opts); qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request, &io_test_opts); + qos_add_test("hce-reset", "ufs", ufs_test_hce_reset, &mcq_test_opts); qos_add_test("wb-init", "ufs", ufstest_wb_init, &wb_test_opts); qos_add_test("wb-read-write", "ufs", ufstest_wb_read_write, &wb_test_o= pts); qos_add_test("hid", "ufs", ufstest_hid, &io_test_opts); --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655230; cv=none; d=zohomail.com; s=zohoarc; b=kb/1mtdLNNUrrfG/qCogCGMRrTCJlniJAvSHtaqDoDZSW8H4kDWLZlEB2A1YH+eDpHELmqrcFTBCI0y+A+3wfx4PBd2xZuYmLHewKiSZpc0xfZfhlX6aJ0tNFcD0rVPdTqDoT8ghUy3RiUTPefKeKqmx5LbWhuteVUjLeIfQMwU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655230; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=xGyOLovLsap1p4IqIEwxFhS43f48xrlGfxUd31VRJ9s=; b=Ubdb2Zxh3GDAZc4ruAUTNpKOe/+VyrVc+iPPGQYbT7PPF8fOYKLKQF+IVYDnlYcPo/rbJmivfQhI5uUTvdRfvudX5QJsOzhwB1cPZkyILf/HDKz2YTRBk2qHfopMRzeKDSn0pFCbKJJbhHDkZL5TnVrq8zg+Lj8SU30LTttsiQk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 179265523042580.47797616870344; Thu, 22 Oct 2026 00:47:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnVu-0008Q8-45; Thu, 22 Oct 2026 03:47:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3Hr_ZagoKCmERS9MKDXIGTFNNFKD.BNLPDLT-CDUDKMNMFMT.NQF@flex--stanleyjhu.bounces.google.com>) id 1xJnUf-0007TQ-JA for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:55 -0400 Received: from mail-pf1-x445.google.com ([2607:f8b0:4864:20::445]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3Hr_ZagoKCmERS9MKDXIGTFNNFKD.BNLPDLT-CDUDKMNMFMT.NQF@flex--stanleyjhu.bounces.google.com>) id 1xJnUZ-0002Ii-Mz for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:44 -0400 Received: by mail-pf1-x445.google.com with SMTP id d2e1a72fcca58-8a0589ff620so1093155b3a.1 for ; Thu, 22 Oct 2026 00:45:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655135; x=1793259935; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=xGyOLovLsap1p4IqIEwxFhS43f48xrlGfxUd31VRJ9s=; b=AhVlsBUCY/MfFO6knmbPJKP2aEeU2zSi8yd/7xFtDd5bs1ZJf1I17YnIW/5LWxyOrd RiqsnFlW3Ny22iF1SG2ewcaP4NQWoLtmF24zr8WbUiJim1o9tep54sKorvE4VZIkC4RQ 2hbDkoFBzJLJuSC1zA13ro//4ZC1EGaSJQZzrMze0MoAZ/cW0pdpATGiQNkdJxWrBvPy ueD4DFqaVmgsRZuIt50pYXlaZIrqDnkpVgpElxHqgluT8D5k0pp3m4IzmxpENLycgpaI qpoqtScBQLF/L8pZCDPNKlUSdFw/KpAF0ykAkG2mUUVd5JGkxw5wogOa8WJFi6COaWoX 3pJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655135; x=1793259935; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=xGyOLovLsap1p4IqIEwxFhS43f48xrlGfxUd31VRJ9s=; b=CpyIvjkkmBIZEePdMR44K306ppvQ47Fy8r+ejcQqtEM+4IEPcLvcW5dq+8PrtJgWP+ rJFXX5Guznz6c63ykswncB1wPQ0mBfdFIhZ79YXLWsrzrwKqorAHLPcnuwi7bSkJ2MuZ R+30SmaMufJSdhsv0fRPWnTKJlFC0OKL3QbfnPtQCeT4ab0SAjOiOjy/KGU4o/9q8fQQ azV5e3n8hFYmoiX9PtwZMzIp/CuITnSs160aZ+X/pSaot6kVOptilrGGSf9/iTIQ5Kvs 6cow3HajoxVBM/Fg9y4xW6UB5QX4u5+nvTDfxVfsT8xBitLpwLdC74+yeg8npzXJsxZl qYSA== X-Gm-Message-State: AFq9FYIwXW+p19pPVCS4XrfjJ5tLxvgtor4hSbEhrXqcOVV0IhQjk3s7 RbB9mH24aXN5uxj6tbz8yAsR9nogk6odzPkZnRxI/eewiJ9Csqe99QqDkhJ3SrBs16f3CRriQdP eBkyDF40r/ivEJXHWsJqMIA== X-Received: from pfak2.prod.google.com ([2002:aa7:92c2:0:b0:88f:2ad7:b21c]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:4213:b0:882:1b4d:1840 with SMTP id d2e1a72fcca58-8a089e40a63mr3370581b3a.24.1792655134796; Thu, 22 Oct 2026 00:45:34 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:12 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-8-stanleyjhu@google.com> Subject: [PATCH v2 7/8] tests/qtest/ufs-test: Add MCQ runtime register and TMR handling test From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::445; envelope-from=3Hr_ZagoKCmERS9MKDXIGTFNNFKD.BNLPDLT-CDUDKMNMFMT.NQF@flex--stanleyjhu.bounces.google.com; helo=mail-pf1-x445.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655232735158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add ufs_test_tmr_handling() to verify UTMRL UFS_QUERY_TASK execution (both interrupt-driven I=3D1 and polling I=3D0 UTMRDs), SQCTI/CQIACR register access, SQRTC/SQRTS queue stop/start and self-clearing ICU transitions across running, stopped, and disabled SQ states, nullified SQE (CT =3D 0xF) completion with UFS_OCS_ABORTED, and CQIS.TEPS write-1-to-clear synchronization with IS.CQES. Signed-off-by: Stanley Jhu --- tests/qtest/ufs-test.c | 161 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 1 deletion(-) diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c index 019107d818..bbc90f2218 100644 --- a/tests/qtest/ufs-test.c +++ b/tests/qtest/ufs-test.c @@ -1899,7 +1899,7 @@ static void ufstest_hid(void *obj, void *data, QGuest= Allocator *alloc) ufs_exit(ufs, alloc); } =20 -static G_GNUC_UNUSED void ufs_send_tmr(QUfs *ufs, uint64_t utmrlba, int sl= ot, +static void ufs_send_tmr(QUfs *ufs, uint64_t utmrlba, int slot, uint8_t tm_func, uint8_t lun, uint32_t task_tag, UtpTaskReqDesc *utrd_out) @@ -2026,6 +2026,164 @@ static void ufs_test_hce_reset(void *obj, void *dat= a, QGuestAllocator *alloc) ufs_exit(ufs, alloc); } =20 +static void ufs_test_tmr_handling(void *obj, void *data, QGuestAllocator *= alloc) +{ + QUfs *ufs =3D obj; + uint64_t utmrlba, desc_addr, req_upiu_addr, rsp_upiu_addr; + UtpTaskReqDesc desc =3D { 0 }, utrd_result; + UtpTransferReqDesc null_utrd; + UtpUpiuReq req_upiu =3D { 0 }; + UfsCqEntry cqe; + uint32_t mcq_reg_offset, sqdao, cqisao, sqrts, sqrtc, orig_sqattr; + int null_slot; + enum UtpOcsCodes ocs; + UtpUpiuRsp rsp_upiu; + + ufs_init(ufs, alloc); + g_assert_true(ufs->support_mcq); + + /* Set up UTMRL */ + utmrlba =3D guest_alloc(alloc, 8 * sizeof(UtpTaskReqDesc)); + ufs_wreg(ufs, A_UTMRLBA, utmrlba & 0xffffffff); + ufs_wreg(ufs, A_UTMRLBAU, utmrlba >> 32); + ufs_wreg(ufs, A_UTMRLRSR, 1); + + /* Issue UFS_QUERY_TASK for inactive tag 15 (Interrupt bit I=3D1) */ + ufs_send_tmr(ufs, utmrlba, 0, UFS_QUERY_TASK, 0, 15, &utrd_result); + g_assert_cmpuint(le32_to_cpu(utrd_result.header.dword_2) & UFS_MASK_OC= S, + =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL); + + /* Issue polling UTMRD with I=3D0 (slot 1): clears doorbell without UT= MRCS */ + desc_addr =3D utmrlba + 1 * sizeof(UtpTaskReqDesc); + desc.header.dword_0 =3D 0; + desc.header.dword_2 =3D cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS); + desc.upiu_req.req_header.trans_type =3D UFS_UPIU_TRANSACTION_TASK_REQ; + desc.upiu_req.req_header.query_func =3D UFS_QUERY_TASK; + desc.upiu_req.req_header.lun =3D 0; + desc.upiu_req.req_header.task_tag =3D 0x11; + desc.upiu_req.input_param1 =3D cpu_to_be32(0); + desc.upiu_req.input_param2 =3D cpu_to_be32(15); + qtest_memwrite(ufs->dev.bus->qts, desc_addr, &desc, sizeof(desc)); + + ufs_wreg(ufs, A_UTMRLDBR, 1 << 1); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLDBR) & (1 << 1), =3D=3D, 0); + g_assert_cmpuint(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTMRCS), =3D=3D, = 0); + qtest_memread(ufs->dev.bus->qts, desc_addr, &utrd_result, + sizeof(utrd_result)); + g_assert_cmpuint(le32_to_cpu(utrd_result.header.dword_2) & UFS_MASK_OC= S, + =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL); + + /* Verify SQCTI, CQIACR, SQRTS/SQRTC, and CQIS/IS.CQES W1C sync */ + sqdao =3D ufs->sqdao[TEST_QID]; + mcq_reg_offset =3D + FIELD_EX32(ufs_rreg(ufs, A_MCQCAP), MCQCAP, QCFGPTR) * 0x200 + + TEST_QID * 0x40; + cqisao =3D ufs_rreg(ufs, mcq_reg_offset + A_CQISAO); + + /* SQCTI and CQIACR read/write */ + ufs_wreg(ufs, sqdao + A_SQCTI, (1 << 8) | 0x2b); + g_assert_cmpuint(ufs_rreg(ufs, sqdao + A_SQCTI), =3D=3D, (1 << 8) | 0x= 2b); + ufs_wreg(ufs, cqisao + offsetof(UfsMcqCqIntReg, iacr), 0x101); + g_assert_cmpuint(ufs_rreg(ufs, cqisao + offsetof(UfsMcqCqIntReg, iacr)= ), + =3D=3D, 0x101); + + /* SQ_ICU while running (STS=3D0) -> sets SQRTS.CUS=3D1, RTC=3D2 */ + ufs_wreg(ufs, sqdao + A_SQRTC, FIELD_DP32(0, SQRTC, ICU, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + sqrtc =3D ufs_rreg(ufs, sqdao + A_SQRTC); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, STS), =3D=3D, 0); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, CUS), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, RTC), =3D=3D, 2); + g_assert_cmpuint(FIELD_EX32(sqrtc, SQRTC, ICU), =3D=3D, 0); + + /* SQ_STOP -> sets SQRTS.STS =3D 1 */ + ufs_wreg(ufs, sqdao + A_SQRTC, FIELD_DP32(0, SQRTC, STOP, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, STS), =3D=3D, 1); + + /* + * SQ_ICU while stopped (no matching req) -> sets SQRTS.CUS=3D1, RTC= =3D1 and + * self-clears ICU. + */ + ufs_wreg(ufs, sqdao + A_SQRTC, + FIELD_DP32(0, SQRTC, STOP, 1) | FIELD_DP32(0, SQRTC, ICU, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + sqrtc =3D ufs_rreg(ufs, sqdao + A_SQRTC); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, STS), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, CUS), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, RTC), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrtc, SQRTC, ICU), =3D=3D, 0); + + /* + * Queue a nullified SQE (CT =3D 0xF) while SQ is stopped, then resume= SQ + * (STOP 1->0): SQRTS.STS clears to 0 while SQRTS.CUS remains 1, and t= he + * nullified SQE posts CQE with UFS_OCS_ABORTED without writing rsp_up= iu. + */ + null_slot =3D alloc_cmd_desc_slot(ufs); + req_upiu_addr =3D + ufs->cmd_desc_addr + null_slot * UTP_COMMAND_DESCRIPTOR_SIZE; + rsp_upiu_addr =3D req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET; + req_upiu.header.trans_type =3D UFS_UPIU_TRANSACTION_NOP_OUT; + req_upiu.header.task_tag =3D null_slot; + qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu, + sizeof(req_upiu)); + memset(&rsp_upiu, 0xa5, sizeof(rsp_upiu)); + qtest_memwrite(ufs->dev.bus->qts, rsp_upiu_addr, &rsp_upiu, + sizeof(rsp_upiu)); + + null_utrd =3D ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSF= ER, 0); + null_utrd.header.dword_0 =3D cpu_to_le32((UFS_UTP_CMD_TYPE_NULL << 28)= | + UFS_UTP_NO_DATA_TRANSFER | + UFS_UTP_REQ_DESC_INT_CMD); + __ufs_send_transfer_request_mcq_async(ufs, 0, &null_utrd); + + /* SQ_START (STOP 1->0) -> clears SQRTS.STS =3D 0 while preserving CUS= =3D 1 */ + ufs_wreg(ufs, sqdao + A_SQRTC, 0); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, STS), =3D=3D, 0); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, CUS), =3D=3D, 1); + + ufs_wait_for_irq(ufs); + g_assert_cmpuint(ufs_mcq_poll_cq(ufs, &cqe, 1), =3D=3D, 1); + g_assert_cmpuint(cqe.status, =3D=3D, UFS_OCS_ABORTED); + g_assert_cmpuint(cqe.task_tag, =3D=3D, null_slot); + qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, &rsp_upiu, + sizeof(rsp_upiu)); + g_assert_cmpuint(rsp_upiu.header.trans_type, =3D=3D, 0xa5); + ufs_wreg(ufs, cqisao + A_CQIS, FIELD_DP32(0, CQIS, TEPS, 1)); + release_cmd_desc_slot(ufs, null_slot); + + /* Verify MCQ command sets CQIS.TEPS=3D1 and W1C clears CQIS.TEPS & IS= .CQES */ + ocs =3D ufs_send_nop_out(ufs, &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(FIELD_EX32(ufs_rreg(ufs, cqisao + A_CQIS), CQIS, TEPS= ), + =3D=3D, 1); + ufs_wreg(ufs, cqisao + A_CQIS, FIELD_DP32(0, CQIS, TEPS, 1)); + g_assert_cmpuint(FIELD_EX32(ufs_rreg(ufs, cqisao + A_CQIS), CQIS, TEPS= ), + =3D=3D, 0); + g_assert_cmpuint(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, CQES), =3D=3D, 0); + + /* SQ_ICU on disabled SQ (SQEN=3D0) -> sets SQRTS.CUS=3D1, RTC=3D3 */ + orig_sqattr =3D ufs_rreg(ufs, mcq_reg_offset + A_SQATTR); + ufs_wreg(ufs, mcq_reg_offset + A_SQATTR, 0); + ufs_wreg(ufs, sqdao + A_SQRTC, FIELD_DP32(0, SQRTC, ICU, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, CUS), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, RTC), =3D=3D, 3); + ufs_wreg(ufs, mcq_reg_offset + A_SQATTR, orig_sqattr); + + guest_free(alloc, utmrlba); + ufs_exit(ufs, alloc); +} + #define ZONE_SIZE (2 * 1024 * 1024) #define ZONE_BLOCKS (ZONE_SIZE / 4096) #define MAX_OPEN_ZONE 6 @@ -3205,6 +3363,7 @@ static void ufs_register_nodes(void) qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request, &io_test_opts); qos_add_test("hce-reset", "ufs", ufs_test_hce_reset, &mcq_test_opts); + qos_add_test("tmr-handling", "ufs", ufs_test_tmr_handling, &mcq_test_o= pts); qos_add_test("wb-init", "ufs", ufstest_wb_init, &wb_test_opts); qos_add_test("wb-read-write", "ufs", ufstest_wb_read_write, &wb_test_o= pts); qos_add_test("hid", "ufs", ufstest_hid, &io_test_opts); --=20 2.56.0.218.g1ec904b173-goog From nobody Fri Oct 23 20:56:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792655229; cv=none; d=zohomail.com; s=zohoarc; b=L29SEawkvk5LOYlUzpNfqKXapJhBhelD2S68UOUqM8gSa1anJn0twsMq+arDc7TI1detmtLgaTWaLtzGGXRSaO9SxE9r3VUZt9fd/B9B1MQHC5W0NhN+1hTBqWNkg9PI/DzuH8Sr8hih35XeJM/NWherYzrVkdAZHJXrYRimoBk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792655229; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UcEROrNm8lSgNBDpxmz5BUzKp4MIbTDaNsyn3XsUJ4k=; b=Ri78AYtCi2szTunEQ2L/HZI+QAmNNE01Q3cJ9GqpyOGyGsC9187/iQXYsrqTMPWpTXZYcm+MjSJy0gHb3+9DjzYI0YCQHBWxgjiwWYQfoQbONpDV9E6r8dvdKLdpfRILYkmgyCasOuU7utR9tZsnYkmt1y2t6nV2zTloT9mlf60= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792655229140953.270649566076; Thu, 22 Oct 2026 00:47:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xJnVr-0008CO-HM; Thu, 22 Oct 2026 03:46:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3IL_ZagoKCmMTUBOMFZKIVHPPHMF.DPNRFNV-EFWFMOPOHOV.PSH@flex--stanleyjhu.bounces.google.com>) id 1xJnUf-0007TR-JI for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:55 -0400 Received: from mail-pf1-x445.google.com ([2607:f8b0:4864:20::445]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3IL_ZagoKCmMTUBOMFZKIVHPPHMF.DPNRFNV-EFWFMOPOHOV.PSH@flex--stanleyjhu.bounces.google.com>) id 1xJnUZ-0002Iq-N2 for qemu-devel@nongnu.org; Thu, 22 Oct 2026 03:45:44 -0400 Received: by mail-pf1-x445.google.com with SMTP id d2e1a72fcca58-8a0688a43d3so1239797b3a.0 for ; Thu, 22 Oct 2026 00:45:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792655137; x=1793259937; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=UcEROrNm8lSgNBDpxmz5BUzKp4MIbTDaNsyn3XsUJ4k=; b=bKud+4kAk997FtTpLKjgAZ0hIuzFk0/SefG8XB+QAM40O6mYDckWmOui6N4HfDGjhN pd56Cvou1UzV/I+Uh+qZW7YHtiY8Xr3+PzOdgxAZMtrTzVhCled6dFqbOIJBn3pZw0i8 pin4tLwSjpj9MQ72d0nEkcN3MDiG5jVARN2Mb4WULiYYLj9irg6OflTqFCyTojZt6FzB PCWtcUbXvb+bwmV4XasGzJ7AIRMuFy4XZvZLVcUMu2X36Q9iPkZkah1OVWuc0uiOLBhq UNw9DTqu6HeowEMg4eKTyJBOICign1wpj0Yr+l9cncM3BDrJEBORm3I0GZKHifTHrcme 5ERA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792655137; x=1793259937; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=UcEROrNm8lSgNBDpxmz5BUzKp4MIbTDaNsyn3XsUJ4k=; b=GBKtoYW9isqkJzuo1PpA1UTtlDpu1Immu8srn8XStswvJsdwHB7ph2om7vAG9ac1Fz ekKwJy6kB3LO3rl5fepelMMt7WvWpWwTCpVY78jH+2O7DPdySLMELukvWbMVbjqdSphE wT7mDIA45BR4u//jcGyH9upWeAIwy1c27HOhmlQE1XGv0r8clEdtOfOu1mKF27shCqT7 Wc0BentOAuMyowhGNFdpO7twU/VBgNhZqU/XMl64Mt4TEZHZHiZlvCiA0X3TGmE8FZQ2 zt8D9JDrEB/KG39XdXzsiUn/voPcXdFT2/VkAyy0sNrGY9zhliNXvwSAL73SJNbu0COD Dd+Q== X-Gm-Message-State: AFq9FYIGvDc5jfveCOCIBjHGTasYaA9dH7/GqTITS4y8OyXrxaVmCSWu zFm6w/zg3lGMt0RrUCn4F9L52tpU8QJctHis0NVGhrbk4Dru0g9ZvchAxe+h8LQFXG1q6O1euUj 12U+GdlwdaK0/w9bgKZrnbA== X-Received: from pfbfh8.prod.google.com ([2002:a05:6a00:3908:b0:893:a6ee:f3c3]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2990:b0:898:f575:7bd0 with SMTP id d2e1a72fcca58-8a089d0d35fmr3478272b3a.22.1792655136730; Thu, 22 Oct 2026 00:45:36 -0700 (PDT) Date: Thu, 22 Oct 2026 15:45:13 +0800 In-Reply-To: <20261022074513.2292281-1-stanleyjhu@google.com> Mime-Version: 1.0 References: <20261022074513.2292281-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.218.g1ec904b173-goog Message-ID: <20261022074513.2292281-9-stanleyjhu@google.com> Subject: [PATCH v2 8/8] tests/qtest/ufs-test: Add QOM fault injection task abort test From: Stanley Jhu To: Jeuk Kim , Jeuk Kim Cc: qemu-devel@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Pierrick Bouvier , Jinyoung Choi , Daejun Park Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::445; envelope-from=3IL_ZagoKCmMTUBOMFZKIVHPPHMF.DPNRFNV-EFWFMOPOHOV.PSH@flex--stanleyjhu.bounces.google.com; helo=mail-pf1-x445.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, 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, T_PDS_OTHER_BAD_TLD=0.01, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792655230628158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add ufs_test_fault_injection_abort() to validate runtime QOM fault injection modes via x-fault-inject-tag and x-fault-inject-mode (abort-success with held-request tag overwrite rejection, two-stage UFS_ABORT_TASK + SQRTC.ICU and LUN matching, in-transition completion, timeout with UTMRLCLR clear-on-zero verification, abort-failed rejection, and ssu-timeout WLUN START_STOP filtering). Signed-off-by: Stanley Jhu --- tests/qtest/ufs-test.c | 333 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 332 insertions(+), 1 deletion(-) diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c index bbc90f2218..8fe53c1b81 100644 --- a/tests/qtest/ufs-test.c +++ b/tests/qtest/ufs-test.c @@ -1928,7 +1928,7 @@ static void ufs_send_tmr(QUfs *ufs, uint64_t utmrlba,= int slot, qtest_memread(ufs->dev.bus->qts, desc_addr, utrd_out, sizeof(*utrd_out= )); } =20 -static G_GNUC_UNUSED int ufs_mcq_send_scsi_cmd_async(QUfs *ufs, uint8_t lu= n, +static int ufs_mcq_send_scsi_cmd_async(QUfs *ufs, uint8_t lun, const uint8_t *cdb) { int cmd_desc_slot =3D alloc_cmd_desc_slot(ufs); @@ -2184,6 +2184,335 @@ static void ufs_test_tmr_handling(void *obj, void *= data, QGuestAllocator *alloc) ufs_exit(ufs, alloc); } =20 +#define UFS_FAULT_INJECT_TAG_NONE 0xffffffffU +#define UFS_FAULT_INJECT_TAG_ANY 0xfffffffeU + +static void ufs_test_fault_injection_abort(void *obj, void *data, + QGuestAllocator *alloc) +{ + QUfs *ufs =3D obj; + QTestState *qts =3D ufs->dev.bus->qts; + uint64_t utmrlba, desc_addr; + UtpTaskReqDesc utrd, utrd_result; + const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] =3D { TEST_UNIT_READY = }; + const uint8_t read10_lba512_cdb[UFS_CDB_SIZE] =3D { + READ_10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const uint8_t start_stop_cdb[UFS_CDB_SIZE] =3D { START_STOP }; + uint32_t sqdao, cqdao, mcq_reg_offset, cqisao, sqrts, cqhp, cqtp; + UfsCqEntry cqe; + int slot; + QDict *rsp; + + ufs_init(ufs, alloc); + g_assert_true(ufs->support_mcq); + + utmrlba =3D guest_alloc(alloc, 8 * sizeof(UtpTaskReqDesc)); + ufs_wreg(ufs, A_UTMRLBA, utmrlba & 0xffffffff); + ufs_wreg(ufs, A_UTMRLBAU, utmrlba >> 32); + ufs_wreg(ufs, A_UTMRLRSR, 1); + + sqdao =3D ufs->sqdao[TEST_QID]; + cqdao =3D ufs->cqdao[TEST_QID]; + mcq_reg_offset =3D + FIELD_EX32(ufs_rreg(ufs, A_MCQCAP), MCQCAP, QCFGPTR) * 0x200 + + TEST_QID * 0x40; + cqisao =3D ufs_rreg(ufs, mcq_reg_offset + A_CQISAO); + + /* + * Case 1: x-fault-inject-mode =3D abort-success (two-stage MCQ abort + + * SQRTC.ICU). + */ + slot =3D find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-mode', 'value': 'abort-success' } }"); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': %d } }", slot); + + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, 0, test_unit_ready_cdb); + qtest_clock_step(qts, 100); + + /* Issue UFS_QUERY_TASK -> assert Target Success & SUCCEEDED (0x08) */ + ufs_send_tmr(ufs, utmrlba, 0, UFS_QUERY_TASK, 0, slot, &utrd_result); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED); + + /* Verify x-fault-inject-tag cannot be overwritten while a req is held= */ + rsp =3D qtest_qmp(qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': 7 } }"); + g_assert_true(qdict_haskey(rsp, "error")); + qobject_unref(rsp); + + /* Issue UFS_ABORT_TASK -> assert COMPL (0x00) and tag cleared */ + ufs_send_tmr(ufs, utmrlba, 0, UFS_ABORT_TASK, 0, slot, &utrd_result); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL); + + rsp =3D qtest_qmp( + qts, + "{ 'execute': 'qom-get', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag' } }"); + g_assert_cmpuint(qdict_get_int(rsp, "return"), =3D=3D, + UFS_FAULT_INJECT_TAG_NONE); + qobject_unref(rsp); + + /* + * UFS_ABORT_TASK alone must NOT post a CQE + * before SQRTC.ICU is issued. + */ + cqhp =3D ufs_rreg(ufs, cqdao); + cqtp =3D ufs_rreg(ufs, cqdao + 0x4); + g_assert_cmpuint(cqtp, =3D=3D, cqhp); + + /* Stop SQ and test SQRTC.ICU with a mismatched LUN (lun=3D1 vs lun=3D= 0) */ + ufs_wreg(ufs, sqdao + A_SQRTC, FIELD_DP32(0, SQRTC, STOP, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, STS), =3D=3D, 1); + + ufs_wreg(ufs, sqdao + A_SQCTI, (1 << 8) | slot); + ufs_wreg(ufs, sqdao + A_SQRTC, + FIELD_DP32(0, SQRTC, STOP, 1) | FIELD_DP32(0, SQRTC, ICU, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, CUS), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, RTC), =3D=3D, 1); + g_assert_cmpuint(ufs_rreg(ufs, cqdao + 0x4), =3D=3D, cqhp); + + /* Issue SQRTC.ICU with matching SQCTI (lun=3D0) -> posts ABORTED CQE = */ + ufs_wreg(ufs, sqdao + A_SQCTI, (0 << 8) | slot); + ufs_wreg(ufs, sqdao + A_SQRTC, + FIELD_DP32(0, SQRTC, STOP, 1) | FIELD_DP32(0, SQRTC, ICU, 1)); + sqrts =3D ufs_rreg(ufs, sqdao + A_SQRTS); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, CUS), =3D=3D, 1); + g_assert_cmpuint(FIELD_EX32(sqrts, SQRTS, RTC), =3D=3D, 0); + + cqtp =3D ufs_rreg(ufs, cqdao + 0x4); + g_assert_cmpuint(cqtp, !=3D, cqhp); + qtest_memread(qts, ufs->cqlba[TEST_QID] + cqhp, &cqe, sizeof(cqe)); + g_assert_cmpuint(cqe.status, =3D=3D, UFS_OCS_ABORTED); + g_assert_cmpuint(cqe.task_tag, =3D=3D, slot); + ufs_wreg(ufs, cqdao, cqtp); + ufs_wreg(ufs, cqisao + A_CQIS, FIELD_DP32(0, CQIS, TEPS, 1)); + ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1)); + ufs_wreg(ufs, sqdao + A_SQRTC, 0); + release_cmd_desc_slot(ufs, slot); + + /* + * Case 2: x-fault-inject-mode =3D in-transition. + * UFS_QUERY_TASK completes the held request normally (UFS_OCS_SUCCESS= CQE). + */ + slot =3D find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-mode', 'value': 'in-transition' } }"); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': %d } }", slot); + + cqhp =3D ufs_rreg(ufs, cqdao); + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, 0, test_unit_ready_cdb); + qtest_clock_step(qts, 100); + + ufs_send_tmr(ufs, utmrlba, 0, UFS_QUERY_TASK, 0, slot, &utrd_result); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_COMPL); + cqtp =3D ufs_rreg(ufs, cqdao + 0x4); + g_assert_cmpuint(cqtp, !=3D, cqhp); + qtest_memread(qts, ufs->cqlba[TEST_QID] + cqhp, &cqe, sizeof(cqe)); + g_assert_cmpuint(cqe.status, =3D=3D, UFS_OCS_SUCCESS); + ufs_wreg(ufs, cqdao, cqtp); + ufs_wreg(ufs, cqisao + A_CQIS, FIELD_DP32(0, CQIS, TEPS, 1)); + ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1)); + release_cmd_desc_slot(ufs, slot); + + /* + * Case 3: x-fault-inject-mode =3D timeout + A_UTMRLCLR clear-on-zero. + * UFS_ABORT_TASK times out, leaving UTMRLDBR bit 2 set. + * + * UFSHCI defines UTMRLCLR as write-0-to-clear: writing 0 to a bit cle= ars + * that slot in UTMRLDBR, writing 1 leaves it unchanged. + */ + slot =3D find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-mode', 'value': 'timeout' } }"); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': %d } }", slot); + + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, 0, test_unit_ready_cdb); + qtest_clock_step(qts, 100); + + memset(&utrd, 0, sizeof(utrd)); + utrd.header.dword_0 =3D cpu_to_le32(UFS_UTP_REQ_DESC_INT_CMD); + utrd.header.dword_2 =3D cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS); + utrd.upiu_req.req_header.trans_type =3D UFS_UPIU_TRANSACTION_TASK_REQ; + utrd.upiu_req.req_header.query_func =3D UFS_ABORT_TASK; + utrd.upiu_req.req_header.lun =3D 0; + utrd.upiu_req.req_header.task_tag =3D 2; + utrd.upiu_req.input_param1 =3D cpu_to_be32(0); + utrd.upiu_req.input_param2 =3D cpu_to_be32(slot); + desc_addr =3D utmrlba + 2 * sizeof(UtpTaskReqDesc); + qtest_memwrite(qts, desc_addr, &utrd, sizeof(utrd)); + + ufs_wreg(ufs, A_UTMRLDBR, 1 << 2); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLDBR) & (1 << 2), =3D=3D, 1 << 2); + + /* + * Writing 1s to A_UTMRLCLR indicates no change per UFSHCI spec, + * so it must NOT clear UTMRLDBR bit 2. + */ + ufs_wreg(ufs, A_UTMRLCLR, 0xffffffffU); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLDBR) & (1 << 2), =3D=3D, 1 << 2); + + /* + * Writing 0 at bit 2 (~(1 << 2)) to A_UTMRLCLR indicates slot cleared, + * so it MUST clear bit 2. + */ + ufs_wreg(ufs, A_UTMRLCLR, ~(1U << 2)); + g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLDBR) & (1 << 2), =3D=3D, 0); + + ufs_wreg(ufs, A_HCE, 0); + release_cmd_desc_slot(ufs, slot); + ufs_exit(ufs, alloc); + ufs_init(ufs, alloc); + ufs_wreg(ufs, A_UTMRLBA, utmrlba & 0xffffffff); + ufs_wreg(ufs, A_UTMRLBAU, utmrlba >> 32); + ufs_wreg(ufs, A_UTMRLRSR, 1); + + /* + * Case 4: x-fault-inject-mode =3D abort-failed. + */ + slot =3D find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-mode', 'value': 'abort-failed' } }"); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': %d } }", slot); + + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, 0, test_unit_ready_cdb); + qtest_clock_step(qts, 100); + + /* Issue UFS_QUERY_TASK -> assert Target Success & SUCCEEDED (0x08) */ + ufs_send_tmr(ufs, utmrlba, 0, UFS_QUERY_TASK, 0, slot, &utrd_result); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED); + + /* Issue UFS_ABORT_TASK -> assert Target Failure & FAILED (0x05) */ + ufs_send_tmr(ufs, utmrlba, 0, UFS_ABORT_TASK, 0, slot, &utrd_result); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_FAIL); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_FAILED); + + /* Reset controller to clear held request cleanly */ + ufs_wreg(ufs, A_HCE, 0); + release_cmd_desc_slot(ufs, slot); + ufs_exit(ufs, alloc); + ufs_init(ufs, alloc); + ufs_wreg(ufs, A_UTMRLBA, utmrlba & 0xffffffff); + ufs_wreg(ufs, A_UTMRLBAU, utmrlba >> 32); + ufs_wreg(ufs, A_UTMRLRSR, 1); + + /* + * Case 5: x-fault-inject-mode =3D ssu-timeout. + * Non-SSU commands on LU 0 complete normally even with a matching + * specific tag or UFS_FAULT_INJECT_TAG_ANY, whereas START_STOP to + * UFS_UPIU_UFS_DEVICE_WLUN is held. + */ + slot =3D find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-mode', 'value': 'ssu-timeout' } }"); + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': %d } }", slot); + + cqhp =3D ufs_rreg(ufs, cqdao); + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, 0, test_unit_ready_cdb); + qtest_clock_step(qts, 100); + cqtp =3D ufs_rreg(ufs, cqdao + 0x4); + g_assert_cmpuint(cqtp, !=3D, cqhp); + qtest_memread(qts, ufs->cqlba[TEST_QID] + cqhp, &cqe, sizeof(cqe)); + g_assert_cmpuint(cqe.status, =3D=3D, UFS_OCS_SUCCESS); + ufs_wreg(ufs, cqdao, cqtp); + ufs_wreg(ufs, cqisao + A_CQIS, FIELD_DP32(0, CQIS, TEPS, 1)); + ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1)); + release_cmd_desc_slot(ufs, slot); + + qtest_qmp_assert_success( + qts, + "{ 'execute': 'qom-set', 'arguments': { " + "'path': '/machine/peripheral/ufs0', " + "'property': 'x-fault-inject-tag', 'value': %u } }", + UFS_FAULT_INJECT_TAG_ANY); + + cqhp =3D ufs_rreg(ufs, cqdao); + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, 0, read10_lba512_cdb); + qtest_clock_step(qts, 100); + cqtp =3D ufs_rreg(ufs, cqdao + 0x4); + g_assert_cmpuint(cqtp, !=3D, cqhp); + qtest_memread(qts, ufs->cqlba[TEST_QID] + cqhp, &cqe, sizeof(cqe)); + g_assert_cmpuint(cqe.status, =3D=3D, UFS_OCS_SUCCESS); + ufs_wreg(ufs, cqdao, cqtp); + ufs_wreg(ufs, cqisao + A_CQIS, FIELD_DP32(0, CQIS, TEPS, 1)); + ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1)); + release_cmd_desc_slot(ufs, slot); + + cqhp =3D ufs_rreg(ufs, cqdao); + slot =3D ufs_mcq_send_scsi_cmd_async(ufs, UFS_UPIU_UFS_DEVICE_WLUN, + start_stop_cdb); + qtest_clock_step(qts, 100); + cqtp =3D ufs_rreg(ufs, cqdao + 0x4); + g_assert_cmpuint(cqtp, =3D=3D, cqhp); + + ufs_send_tmr(ufs, utmrlba, 0, UFS_QUERY_TASK, UFS_UPIU_UFS_DEVICE_WLUN, + slot, &utrd_result); + g_assert_cmpuint(utrd_result.upiu_rsp.rsp_header.response, + =3D=3D, UFS_COMMAND_RESULT_SUCCESS); + g_assert_cmpuint(be32_to_cpu(utrd_result.upiu_rsp.output_param1), + =3D=3D, UFS_UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED); + + ufs_wreg(ufs, A_HCE, 0); + release_cmd_desc_slot(ufs, slot); + + guest_free(alloc, utmrlba); + ufs_exit(ufs, alloc); +} + #define ZONE_SIZE (2 * 1024 * 1024) #define ZONE_BLOCKS (ZONE_SIZE / 4096) #define MAX_OPEN_ZONE 6 @@ -3364,6 +3693,8 @@ static void ufs_register_nodes(void) &io_test_opts); qos_add_test("hce-reset", "ufs", ufs_test_hce_reset, &mcq_test_opts); qos_add_test("tmr-handling", "ufs", ufs_test_tmr_handling, &mcq_test_o= pts); + qos_add_test("fault-injection-abort", "ufs", + ufs_test_fault_injection_abort, &mcq_test_opts); qos_add_test("wb-init", "ufs", ufstest_wb_init, &wb_test_opts); qos_add_test("wb-read-write", "ufs", ufstest_wb_read_write, &wb_test_o= pts); qos_add_test("hid", "ufs", ufstest_hid, &io_test_opts); --=20 2.56.0.218.g1ec904b173-goog