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
|
#ifdef TARGET_AARCH64
|
||||||
static uint64_t tlbi_aa64_range_get_length(CPUARMState *env,
|
typedef struct {
|
||||||
uint64_t value)
|
uint64_t base;
|
||||||
{
|
|
||||||
unsigned int page_shift;
|
|
||||||
unsigned int page_size_granule;
|
|
||||||
uint64_t num;
|
|
||||||
uint64_t scale;
|
|
||||||
uint64_t exponent;
|
|
||||||
uint64_t length;
|
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);
|
page_size_granule = extract64(value, 46, 2);
|
||||||
|
|
||||||
if (page_size_granule == 0) {
|
if (page_size_granule == 0) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
|
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
|
||||||
page_size_granule);
|
page_size_granule);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
page_shift = (page_size_granule - 1) * 2 + 12;
|
page_shift = (page_size_granule - 1) * 2 + 12;
|
||||||
|
num = extract64(value, 39, 5);
|
||||||
|
scale = extract64(value, 44, 2);
|
||||||
exponent = (5 * scale) + 1;
|
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,
|
if (regime_has_2_ranges(mmuidx)) {
|
||||||
bool two_ranges)
|
ret.base = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||||
{
|
|
||||||
/* TODO: ARMv8.7 FEAT_LPA2 */
|
|
||||||
uint64_t pageaddr;
|
|
||||||
|
|
||||||
if (two_ranges) {
|
|
||||||
pageaddr = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
|
|
||||||
} else {
|
} 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,
|
static void do_rvae_write(CPUARMState *env, uint64_t value,
|
||||||
int idxmap, bool synced)
|
int idxmap, bool synced)
|
||||||
{
|
{
|
||||||
ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
|
ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
|
||||||
bool two_ranges = regime_has_2_ranges(one_idx);
|
TLBIRange range;
|
||||||
uint64_t baseaddr, length;
|
|
||||||
int bits;
|
int bits;
|
||||||
|
|
||||||
baseaddr = tlbi_aa64_range_get_base(env, value, two_ranges);
|
range = tlbi_aa64_get_range(env, one_idx, value);
|
||||||
length = tlbi_aa64_range_get_length(env, value);
|
bits = tlbbits_for_regime(env, one_idx, range.base);
|
||||||
bits = tlbbits_for_regime(env, one_idx, baseaddr);
|
|
||||||
|
|
||||||
if (synced) {
|
if (synced) {
|
||||||
tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
|
tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
|
||||||
baseaddr,
|
range.base,
|
||||||
length,
|
range.length,
|
||||||
idxmap,
|
idxmap,
|
||||||
bits);
|
bits);
|
||||||
} else {
|
} else {
|
||||||
tlb_flush_range_by_mmuidx(env_cpu(env), baseaddr,
|
tlb_flush_range_by_mmuidx(env_cpu(env), range.base,
|
||||||
length, idxmap, bits);
|
range.length, idxmap, bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user