diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-11-30 17:32:57 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-12-15 10:35:26 +0000 |
commit | 52a9f60935d394953dd6b47d01bb7eb47bc2592f (patch) | |
tree | 2f48a9c82809909e19171e82bdc96b929d85571f /target/arm | |
parent | 3508c0fac2b7055a341d30e67968506c7ed4f797 (diff) | |
download | qemu-52a9f60935d394953dd6b47d01bb7eb47bc2592f.zip qemu-52a9f60935d394953dd6b47d01bb7eb47bc2592f.tar.gz qemu-52a9f60935d394953dd6b47d01bb7eb47bc2592f.tar.bz2 |
target/arm: Correct calculation of tlb range invalidate length
The calculation of the length of TLB range invalidate operations
in tlbi_aa64_range_get_length() is incorrect in two ways:
* the NUM field is 5 bits, but we read only 4 bits
* we miscalculate the page_shift value, because of an
off-by-one error:
TG 0b00 is invalid
TG 0b01 is 4K granule size == 4096 == 2^12
TG 0b10 is 16K granule size == 16384 == 2^14
TG 0b11 is 64K granule size == 65536 == 2^16
so page_shift should be (TG - 1) * 2 + 12
Thanks to the bug report submitter Cha HyunSoo for identifying
both these errors.
Fixes: 84940ed82552d3c ("target/arm: Add support for FEAT_TLBIRANGE")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/734
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20211130173257.1274194-1-peter.maydell@linaro.org
Diffstat (limited to 'target/arm')
-rw-r--r-- | target/arm/helper.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 9b31789..db837d5 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -4519,18 +4519,18 @@ static uint64_t tlbi_aa64_range_get_length(CPUARMState *env, uint64_t exponent; uint64_t length; - num = extract64(value, 39, 4); + num = extract64(value, 39, 5); scale = extract64(value, 44, 2); page_size_granule = extract64(value, 46, 2); - page_shift = page_size_granule * 2 + 12; - if (page_size_granule == 0) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n", page_size_granule); return 0; } + page_shift = (page_size_granule - 1) * 2 + 12; + exponent = (5 * scale) + 1; length = (num + 1) << (exponent + page_shift); |