From nobody Mon Feb 9 15:25:48 2026 Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC4501624D5 for ; Sun, 21 Dec 2025 01:43:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766281396; cv=none; b=CfzOjb5hu1ihck/CFdajaEtJs++hmXVCic9GClKn52jg9olo34+co8nYFAjNvFDkEcKkPqb0HQO4CkkKRGF5m8Ye5YHwVqwFMlYdbaF7fee570svyfQZIyuC0eTHUEOg8f0WjWCrCrMN7AfOSQfBFuDHSfPRa2NwjbWJEn6fu8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766281396; c=relaxed/simple; bh=c6l+DaU5BDXL/1UKC1uRvyXoD6pUE+hzGySChC03UOU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cRkppXPSLIFtvEfzPPLiwmlkHre2PSw2p1/p7UhJROYGkuCO1PfBlYecEaHy8VfM2b1DzQ0+gg66XNb1HFxjsSYdJ35nXo15a6/PHQbjnvRsHz3jg6mSXlYXP3FyhAcJkGFIuxScLvCibWsJV8QQ+C2yQh9oBCnVW4LgTU+h+zc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=ApfP8sKO; arc=none smtp.client-ip=209.85.208.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="ApfP8sKO" Received: by mail-ed1-f50.google.com with SMTP id 4fb4d7f45d1cf-63c489f1e6cso2643054a12.1 for ; Sat, 20 Dec 2025 17:43:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1766281393; x=1766886193; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zzPkvFiJPIiBH8gY2E1M7voQ7WOeiTfZU7yF7kFKn4c=; b=ApfP8sKOdHwQpJMlhdxAYIXh4UBRQ1E9FaHGpZWlSd3+dPymMx2PkVZkHEkqlG3gGz ztyQvwxLmjk6sjO1R9aexxhTopem4ygxDjnysCd5vfqyWOZHpxn7/PTMm0wzU1MNh5Zj Fgl4WCulWksXbcpiyMDLki5huCj8wMQqYqcts= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766281393; x=1766886193; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=zzPkvFiJPIiBH8gY2E1M7voQ7WOeiTfZU7yF7kFKn4c=; b=u90D6tWY46H3HZqoHUAV5ibBvqOicKqswyp/ZPQ4WMwgM44c/dziuZPzHFjZDAgxzD +UtMbuzOeGBhCNfVpsRhifbB5qbhj5n1zmdLyNg4XtnY3EuF6812iNzyF9E+fJ2LTQ15 +2rw+wji/5/4i+k1NEVj12Gmtvs0PyLf0jKLwkbGEazDbCmMWjuuGpXkrgQR8LOAa1La zinW8Imd/YvR9i2hr2gGx365pEEqasOX/AIvBwPaTNbRBHab610FYUy4GnsplJOIDlCd vcgK8OnesGbgEG0t7RlHfF45WMUA3cm4jyROIK9IGT4ilOWOhEAkdLeekxG18hqGPGyv PDpw== X-Forwarded-Encrypted: i=1; AJvYcCXtQMJhTDDHQOHFAKy/PA4rQzwuD75wLdp2hCJGeiVZHdVhMCHmfKcgTJ2EXgaIyTlb9n83TUbOKL/Qyuo=@vger.kernel.org X-Gm-Message-State: AOJu0YyPGH3Z1/ktd5g7uovvo2P8pOkQ1pSqFk7jEFKmSdh/+GYW8K1s pEl7ML3aX9EhHWkTkC5iQ3NMG3fXGYlaMZGZqpU3OrJCS3IsgC68C5CwkO3QEnfTLw== X-Gm-Gg: AY/fxX7F1br207Awnk6rm8WQKIc8vT+KoJdCxm9hxfaT/hKY8XLleESTCMpvwwSmUWo bqzwo9nUkdW+OFZjL1Xb2gfp8ShbRkcevg0ghUXNIIdt5lWd39+knIQBXMBIS+F2wjsZj/GaK6H Mr8C8PaxYMdLGUU34BN9lM9obqBOJVMcUEV22WG7fQqsbUjJuZ4CU3xtJOqEERjlzF+WLC7cBfB b1kdChwP0v5em+FVi0gu7QkydsRlMC2N1ww4YYZtMbJfvKVaSWghkG2eKycNbh+6F7S7E+BvUQX vTtVlhbLsHuRzqeHjF91WCeVYm5BbS3kh3Q1cHmzdzbGo615JIUhuB5E5iwXTxhkFx8ktkSgay2 gFnMtK0tlZPVnKQTyT8gINedShf4ePbytmYtlWB/kUfnnnWbTXzF1xRDJpsCsBeaFcNo6r4Q7Fp CNJT9BmVBs9nLnbmvF3DPsmEjXyYxv1w== X-Google-Smtp-Source: AGHT+IESd/5ZjLIUwnYgaHogwawMT0Vq1dN1amO4mHbs9tVB78ygz08actIt/pnZ5iaj+QSjD2Ia6w== X-Received: by 2002:a05:6402:1467:b0:64b:5851:5e7b with SMTP id 4fb4d7f45d1cf-64b8d34f12dmr7723823a12.14.1766281393302; Sat, 20 Dec 2025 17:43:13 -0800 (PST) Received: from localhost.localdomain ([2a02:a31b:20c3:6680:4cc9:1698:dce5:4976]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-64b91494cd7sm6035057a12.16.2025.12.20.17.43.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Dec 2025 17:43:12 -0800 (PST) From: Dmytro Maluka To: David Woodhouse , Lu Baolu , iommu@lists.linux.dev Cc: Joerg Roedel , Will Deacon , Robin Murphy , linux-kernel@vger.kernel.org, "Vineeth Pillai (Google)" , Aashish Sharma , Grzegorz Jaszczyk , Chuanxiao Dong , Kevin Tian , Dmytro Maluka Subject: [PATCH 1/2] iommu/vt-d: Ensure memory ordering in context entry updates Date: Sun, 21 Dec 2025 02:43:01 +0100 Message-ID: <20251221014302.17738-2-dmaluka@chromium.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251221014302.17738-1-dmaluka@chromium.org> References: <20251221014302.17738-1-dmaluka@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When updating context table entries, we do take care to set the present bit as the last step, i.e. in the following order: context_clear_entry(context); context_set_present(context); However, we don't actually ensure this order, i.e. don't prevent the compiler from reordering it. And since context entries may be updated at runtime when translation is already enabled, this may potentially allow a time window when a device can already do DMA while the translation is not properly set up yet (e.g. the context entry may point to an arbitrary page table). To easily fix this, change context_set_*() and context_clear_*() helpers to use READ_ONCE/WRITE_ONCE, to ensure that the ordering between updates of individual bits in context entries matches the order of calling those helpers, just like we already do for PASID table entries. Link: https://lore.kernel.org/all/aTG7gc7I5wExai3S@google.com/ Signed-off-by: Dmytro Maluka --- drivers/iommu/intel/iommu.h | 37 +++++++++++++++++++++---------------- drivers/iommu/intel/pasid.c | 3 ++- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 25c5e22096d4..7f8f004fa756 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -869,7 +869,7 @@ static inline bool dma_pte_superpage(struct dma_pte *pt= e) =20 static inline bool context_present(struct context_entry *context) { - return (context->lo & 1); + return READ_ONCE(context->lo) & 1; } =20 #define LEVEL_STRIDE (9) @@ -897,46 +897,51 @@ static inline int pfn_level_offset(u64 pfn, int level) return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; } =20 +static inline void context_set_bits(u64 *ptr, u64 mask, u64 bits) +{ + u64 old; + + old =3D READ_ONCE(*ptr); + WRITE_ONCE(*ptr, (old & ~mask) | bits); +} =20 static inline void context_set_present(struct context_entry *context) { - context->lo |=3D 1; + context_set_bits(&context->lo, 1 << 0, 1); } =20 static inline void context_set_fault_enable(struct context_entry *context) { - context->lo &=3D (((u64)-1) << 2) | 1; + context_set_bits(&context->lo, 1 << 1, 0); } =20 static inline void context_set_translation_type(struct context_entry *cont= ext, unsigned long value) { - context->lo &=3D (((u64)-1) << 4) | 3; - context->lo |=3D (value & 3) << 2; + context_set_bits(&context->lo, GENMASK_ULL(3, 2), value << 2); } =20 static inline void context_set_address_root(struct context_entry *context, unsigned long value) { - context->lo &=3D ~VTD_PAGE_MASK; - context->lo |=3D value & VTD_PAGE_MASK; + context_set_bits(&context->lo, VTD_PAGE_MASK, value); } =20 static inline void context_set_address_width(struct context_entry *context, unsigned long value) { - context->hi |=3D value & 7; + context_set_bits(&context->hi, GENMASK_ULL(2, 0), value); } =20 static inline void context_set_domain_id(struct context_entry *context, unsigned long value) { - context->hi |=3D (value & ((1 << 16) - 1)) << 8; + context_set_bits(&context->hi, GENMASK_ULL(23, 8), value << 8); } =20 static inline void context_set_pasid(struct context_entry *context) { - context->lo |=3D CONTEXT_PASIDE; + context_set_bits(&context->lo, CONTEXT_PASIDE, CONTEXT_PASIDE); } =20 static inline int context_domain_id(struct context_entry *c) @@ -946,8 +951,8 @@ static inline int context_domain_id(struct context_entr= y *c) =20 static inline void context_clear_entry(struct context_entry *context) { - context->lo =3D 0; - context->hi =3D 0; + WRITE_ONCE(context->lo, 0); + WRITE_ONCE(context->hi, 0); } =20 #ifdef CONFIG_INTEL_IOMMU @@ -980,7 +985,7 @@ clear_context_copied(struct intel_iommu *iommu, u8 bus,= u8 devfn) static inline void context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasi= d) { - context->hi |=3D pasid & ((1 << 20) - 1); + context_set_bits(&context->hi, GENMASK_ULL(19, 0), pasid); } =20 /* @@ -989,7 +994,7 @@ context_set_sm_rid2pasid(struct context_entry *context,= unsigned long pasid) */ static inline void context_set_sm_dte(struct context_entry *context) { - context->lo |=3D BIT_ULL(2); + context_set_bits(&context->lo, BIT_ULL(2), BIT_ULL(2)); } =20 /* @@ -998,7 +1003,7 @@ static inline void context_set_sm_dte(struct context_e= ntry *context) */ static inline void context_set_sm_pre(struct context_entry *context) { - context->lo |=3D BIT_ULL(4); + context_set_bits(&context->lo, BIT_ULL(4), BIT_ULL(4)); } =20 /* @@ -1007,7 +1012,7 @@ static inline void context_set_sm_pre(struct context_= entry *context) */ static inline void context_clear_sm_pre(struct context_entry *context) { - context->lo &=3D ~BIT_ULL(4); + context_set_bits(&context->lo, BIT_ULL(4), 0); } =20 /* Returns a number of VTD pages, but aligned to MM page size */ diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index 77b9b147ab50..7e2b75bcecd4 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -984,7 +984,8 @@ static int context_entry_set_pasid_table(struct context= _entry *context, context_clear_entry(context); =20 pds =3D context_get_sm_pds(table); - context->lo =3D (u64)virt_to_phys(table->table) | context_pdts(pds); + WRITE_ONCE(context->lo, + (u64)virt_to_phys(table->table) | context_pdts(pds)); context_set_sm_rid2pasid(context, IOMMU_NO_PASID); =20 if (info->ats_supported) --=20 2.47.3