[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <9dcd1fbbee53485fa1787f8f86ea879f526d3654.1768900340.git.houwenlong.hwl@antgroup.com>
Date: Tue, 20 Jan 2026 21:44:30 +0800
From: Hou Wenlong <houwenlong.hwl@...group.com>
To: linux-kernel@...r.kernel.org
Cc: Hou Wenlong <houwenlong.hwl@...group.com>,
Dave Hansen <dave.hansen@...ux.intel.com>,
Andy Lutomirski <luto@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Thomas Gleixner <tglx@...nel.org>,
Ingo Molnar <mingo@...hat.com>,
Borislav Petkov <bp@...en8.de>,
x86@...nel.org,
"H. Peter Anvin" <hpa@...or.com>,
Rik van Riel <riel@...riel.com>
Subject: [PATCH v2 4/4] x86/mm: Reset global ASID space when ASID rollover
The global ASID allocation always searches for free ASIDs starting from
the last allocated ASID and resets the ASID space when the last
allocated ASID reaches the edge of the available ASID space. However,
this approach fails in scenarios where the maximum ASID is allocated
first and a smaller ASID is freed later. In such cases, the
'last_global_asid' may never reach the edge of the available ASID space,
leading to allocation failures even when global ASIDs are available.
For example, if all ASIDs are allocated in the first round and then a
smaller ASID is freed, the ASID space can be reset because
'last_global_asid' equals 'MAX_ASID_AVAILABLE - 1'. The smaller ASID can
then be allocated, and 'last_global_asid' is updated accordingly.
However, when this smaller ASID is freed again, the allocation will fail
since 'last_global_asid' no longer equals 'MAX_ASID_AVAILABLE - 1',
preventing the ASID space from being reset. To address this issue, the
global ASID space should be reset based on ASID rollover rather than
depending on the value of 'last_global_asid'.
Fixes: d504d1247e36 ("x86/mm: Add global ASID allocation helper functions")
Signed-off-by: Hou Wenlong <houwenlong.hwl@...group.com>
---
arch/x86/mm/tlb.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index a7dbf784efd9..0f98b78a48cc 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -316,16 +316,18 @@ static void reset_global_asid_space(void)
static u16 allocate_global_asid(void)
{
u16 asid;
+ bool reset = false;
lockdep_assert_held(&global_asid_lock);
- /* The previous allocation hit the edge of available address space */
- if (last_global_asid >= MAX_ASID_AVAILABLE - 1)
- reset_global_asid_space();
-
+restart:
asid = find_next_zero_bit(global_asid_used, MAX_ASID_AVAILABLE, last_global_asid);
-
if (asid >= MAX_ASID_AVAILABLE) {
+ if (!reset) {
+ reset_global_asid_space();
+ reset = true;
+ goto restart;
+ }
/* This should never happen. */
VM_WARN_ONCE(1, "Unable to allocate global ASID despite %d available\n",
global_asid_available);
--
2.31.1
Powered by blists - more mailing lists