target/arm: Introduce tlbi_aa64_get_range
Merge tlbi_aa64_range_get_length and tlbi_aa64_range_get_base, returning a structure containing both results. Pass in the ARMMMUIdx, rather than the digested two_ranges boolean. This is in preparation for FEAT_LPA2, where the interpretation of 'value' depends on the effective value of DS for the regime. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220301215958.157011-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
13e481c933
commit
ab1cdb47bf
@ -4511,70 +4511,60 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
}
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
static uint64_t tlbi_aa64_range_get_length(CPUARMState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
unsigned int page_shift;
|
||||
unsigned int page_size_granule;
|
||||
uint64_t num;
|
||||
uint64_t scale;
|
||||
uint64_t exponent;
|
||||
typedef struct {
|
||||
uint64_t base;
|
||||
uint64_t length;
|
||||
} TLBIRange;
|
||||
|
||||
static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
|
||||
uint64_t value)
|
||||
{
|
||||
unsigned int page_size_granule, page_shift, num, scale, exponent;
|
||||
TLBIRange ret = { };
|
||||
|
||||
num = extract64(value, 39, 5);
|
||||
scale = extract64(value, 44, 2);
|
||||
page_size_granule = extract64(value, 46, 2);
|
||||
|
||||
if (page_size_granule == 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
|
||||
page_size_granule);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
page_shift = (page_size_granule - 1) * 2 + 12;
|
||||
|
||||
num = extract64(value, 39, 5);
|
||||
scale = extract64(value, 44, 2);
|
||||
exponent = (5 * scale) + 1;
|
||||
length = (num + 1) << (exponent + page_shift);
|
||||
|
||||
return length;
|
||||
}
|
||||
ret.length = (num + 1) << (exponent + page_shift);
|
||||
|
||||
static uint64_t tlbi_aa64_range_get_base(CPUARMState *env, uint64_t value,
|
||||
bool two_ranges)
|
||||
{
|
||||
/* TODO: ARMv8.7 FEAT_LPA2 */
|
||||
uint64_t pageaddr;
|
||||
|
||||
if (two_ranges) {
|
||||
pageaddr = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||
if (regime_has_2_ranges(mmuidx)) {
|
||||
ret.base = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||
} else {
|
||||
pageaddr = extract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||
ret.base = extract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||
}
|
||||
|
||||
return pageaddr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void do_rvae_write(CPUARMState *env, uint64_t value,
|
||||
int idxmap, bool synced)
|
||||
{
|
||||
ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
|
||||
bool two_ranges = regime_has_2_ranges(one_idx);
|
||||
uint64_t baseaddr, length;
|
||||
TLBIRange range;
|
||||
int bits;
|
||||
|
||||
baseaddr = tlbi_aa64_range_get_base(env, value, two_ranges);
|
||||
length = tlbi_aa64_range_get_length(env, value);
|
||||
bits = tlbbits_for_regime(env, one_idx, baseaddr);
|
||||
range = tlbi_aa64_get_range(env, one_idx, value);
|
||||
bits = tlbbits_for_regime(env, one_idx, range.base);
|
||||
|
||||
if (synced) {
|
||||
tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
|
||||
baseaddr,
|
||||
length,
|
||||
range.base,
|
||||
range.length,
|
||||
idxmap,
|
||||
bits);
|
||||
} else {
|
||||
tlb_flush_range_by_mmuidx(env_cpu(env), baseaddr,
|
||||
length, idxmap, bits);
|
||||
tlb_flush_range_by_mmuidx(env_cpu(env), range.base,
|
||||
range.length, idxmap, bits);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user