target/arm:Set lg_page_size to 0 if either S1 or S2 asks for it
In get_phys_addr_twostage() we set the lg_page_size of the result to the maximum of the stage 1 and stage 2 page sizes. This works for the case where we do want to create a TLB entry, because we know the common TLB code only creates entries of the TARGET_PAGE_SIZE and asking for a size larger than that only means that invalidations invalidate the whole larger area. However, if lg_page_size is smaller than TARGET_PAGE_SIZE this effectively means "don't create a TLB entry"; in this case if either S1 or S2 said "this covers less than a page and can't go in a TLB" then the final result also should be marked that way. Set the resulting page size to 0 if either stage asked for a less-than-a-page entry, and expand the comment to explain what's going on. This has no effect for VMSA because currently the VMSA lookup always returns results that cover at least TARGET_PAGE_SIZE; however when we add v8R support it will reuse this code path, and for v8R the S1 and S2 results can be smaller than TARGET_PAGE_SIZE. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20221212142708.610090-1-peter.maydell@linaro.org
This commit is contained in:
parent
cb9c6a8e5a
commit
9e65f4e6da
@ -2655,10 +2655,20 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the maximum of the S1 & S2 page size, so that invalidation
|
||||
* of pages > TARGET_PAGE_SIZE works correctly.
|
||||
* If either S1 or S2 returned a result smaller than TARGET_PAGE_SIZE,
|
||||
* this means "don't put this in the TLB"; in this case, return a
|
||||
* result with lg_page_size == 0 to achieve that. Otherwise,
|
||||
* use the maximum of the S1 & S2 page size, so that invalidation
|
||||
* of pages > TARGET_PAGE_SIZE works correctly. (This works even though
|
||||
* we know the combined result permissions etc only cover the minimum
|
||||
* of the S1 and S2 page size, because we know that the common TLB code
|
||||
* never actually creates TLB entries bigger than TARGET_PAGE_SIZE,
|
||||
* and passing a larger page size value only affects invalidations.)
|
||||
*/
|
||||
if (result->f.lg_page_size < s1_lgpgsz) {
|
||||
if (result->f.lg_page_size < TARGET_PAGE_BITS ||
|
||||
s1_lgpgsz < TARGET_PAGE_BITS) {
|
||||
result->f.lg_page_size = 0;
|
||||
} else if (result->f.lg_page_size < s1_lgpgsz) {
|
||||
result->f.lg_page_size = s1_lgpgsz;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user