Re: [PATCH] arm64: hugetlb: fix BBM for mprotect() on contiguous PTEs
From: Ryan Roberts
Date: Fri Sep 04 2026 - 07:12:40 EST
On 03/09/2026 11:45, Will Deacon wrote:
> On Wed, Sep 02, 2026 at 08:16:36PM +0530, Dev Jain wrote:
>>
>>
>> On 01/09/26 6:48 pm, Karl Mehltretter wrote:
>>> huge_ptep_modify_prot_start() clears a hugetlb entry before changing its
>>> permissions. For contiguous PTE mappings, break-before-make (BBM)
>>> requires a TLB invalidation after clearing the set and before making any
>>> entry valid again.
>>>
>>> Commit fb396bb459c1 ("arm64/hugetlb: Drop TLB flush from
>>> get_clear_flush()") removed this invalidation, relying on the deferred
>>> flush from the core code. Commit 410982303772 ("arm64: hugetlb: Restore
>>> TLB invalidation for BBM on contiguous ptes") restored it for
>>> huge_ptep_set_{access_flags,wrprotect}(), since a deferred flush is too
>>> late for the break step. The modify-prot path has the same problem.
>>>
>>> Use huge_ptep_clear_flush() for contiguous entries so that the TLB is
>>> invalidated during the break step. Leave huge_ptep_get_and_clear()
>>> unchanged because it is also used by teardown paths, where the deferred
>>> flush is sufficient.
>>>
>>> Fixes: fb396bb459c1 ("arm64/hugetlb: Drop TLB flush from get_clear_flush()")
>>> Assisted-by: LLM
>>> Signed-off-by: Karl Mehltretter <kmehltretter@xxxxxxxxx>
>>> ---
>>
>> The transition happening here is:
>>
>> old_prot+cont -> zero -> new_prot+cont ... (i)
>> and then TLB flush.
>>
>> Arm Arm rule R_JQQTC says:
>> "For a TLB lookup in a contiguous region mapped by translation table entries
>> that have consistent values for the Contiguous bit, but have the OA, attributes,
>> or permissions misprogrammed, that TLB lookup is permitted to produce an OA,
>> access permissions, and memory attributes that are consistent with any one
>> of the programmed translation table values."
>>
>> This implies that a live update like
>> old_prot+cont -> new_prot+cont then TLB flush ... (ii)
>>
>> is safe. Which should also imply that the transition (i) is safe,
>> since the configurations the PE can observe for (ii) is the same
>> for (i), except that in (ii) the PE can fault too, which is fine.
>
> I'm not sure I agree. As written, the text above says that if the
> permissions are misprogrammed (which they are in this case) then the TLB
> can produce an OA consistent with any of the entries. Hopefully it just
> needs some further clarification.
I'm not sure I understand your concern here. Is your concern that the OA could
be pulled from one of the invalid entries? The intent is that any entry that
does not have the VALID bit set is not considered an "entry" within the
"contiguous range" for the purposes of this. (because it is invalid).
That's implied (if you squint) from:
IPGVGZ: The Contiguous bit is present only in valid Block and Page translation
table descriptors, and therefore neither of the following configurations are
considered as misprogramming of the Contiguous bit:
- A contiguous range of descriptors that are each either invalid, or valid
with Contiguous set to 1.
- A contiguous range of descriptors that are each either invalid, or valid
with Contiguous set to 0.
In general I am of the opinion that the rules around contiguous mappings are not
as clear as they could be and the VMSA architect has indicated that he hopes to
clean them up over time. Bit I don't quite see your concern in this case.
>
> There are probably also cases where we're changing the attributes and the
> permissions at the same time, so it's not clear to me that it's safe to
> allow those to be inconsistent (e.g. tagged/guarded vs read/write). If
> I was going from untagged read/write -> tagged read-only then I presumably
> wouldn't expect to see a tag check fault on a write?
Again, I'm not sure I follow, but I'll take a stab. I think you're implying that
a write permission fault should take precedence over a tag check fault? (I have
no idea off the top of my head). And you're further implying that with this
transition the HW might see an intermediate "tagged read/write" entry, and if it
does then it will raise a tag check fault, not a write fault for an attempted
write. But I don't see how R_JQQTC permits that because it says "consistent with
any one of the programmed translation table values" so the HW can't pick
attributes from one entry and permissions from another. It will either see the
old "untagged read/write" or the new "tagged read-only".
Sorry if I've missed the point!!
Thanks,
Ryan
>
> Will