[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v8 2/4] target/arm: Add support for FEAT_TLBIRANGE
From: |
Richard Henderson |
Subject: |
Re: [PATCH v8 2/4] target/arm: Add support for FEAT_TLBIRANGE |
Date: |
Sat, 8 May 2021 09:39:33 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.7.1 |
On 5/4/21 8:04 PM, Rebecca Cran wrote:
+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;
+ uint64_t length;
+
+ num = extract64(value, 39, 4);
+ scale = extract64(value, 44, 2);
+ page_size_granule = extract64(value, 46, 2);
+
+ page_shift = page_size_granule * 2 + 10;
Should be + 12, for the sequence 12, 14, 16 (4k, 16k, 64k).
+static void tlbi_aa64_rvae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /*
+ * Invalidate by VA range, EL1&0.
+ * Currently handles all of RVAE1, RVAAE1, RVAALE1 and RVALE1,
+ * since we don't support flush-for-specific-ASID-only or
+ * flush-last-level-only.
+ */
+ ARMMMUIdx mmu_idx;
+ int mask;
+ int bits;
+ uint64_t pageaddr;
+ uint64_t length;
+
+ CPUState *cs = env_cpu(env);
+ mask = vae1_tlbmask(env);
+ mmu_idx = ARM_MMU_IDX_A | ctz32(mask);
+ if (regime_has_2_ranges(mmu_idx)) {
+ pageaddr = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
+ } else {
+ pageaddr = extract64(value, 0, 37) << TARGET_PAGE_BITS;
+ }
Let's extract the base address via a helper as well. Add
/* TODO: ARMv8.7 FEAT_LPA2 */
as that will change the extracted base address.
I think there's enough replicated between these functions to want a common
function. Something like
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;
int bits;
baseaddr = tlbi_aa64_range_get_base(env, value, two_ranges);
length = tlb_aa64_range_get_length(env, value);
bits = tlbbits_for_regime(env, one_idx, baseaddr);
if (synced) {
tlb_flush_range_by_mmuidx_all_cpus_synced(...);
} else {
tlb_flush_range_by_mmuidx(...);
}
}
static void tlbi_aa64_rvae1_write(...)
{
do_rvae_write(env, value, vae1_tlbmask(env),
tlb_force_broadcast(env));
}
static void tlbi_aa64_rvae1is_write(...)
{
do_rvae_write(env, value, vae1_tlbmask(env), true);
}
static int vae2_tlbmask(CPUARMState *env)
{
return (arm_is_secure_below_el3(env)
? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2);
}
static void tlbi_aa64_rvae2_write(...)
{
do_rvae_write(env, value, vae2_tlbmask(env),
tlb_force_broadcast(env));
}
static void tlbi_aa64_rvae2is_write(...)
{
do_rvae_write(env, value, vae2_tlbmask(env), true);
}
static void tlbi_aa64_rvae3_write(...)
{
do_rvae_write(env, value, ARMMMUIdxBit_SE3,
tlb_force_broadcast(env));
}
static void tlbi_aa64_rvae3is_write(...)
{
do_rvae_write(env, value, ARMMMUIdxBit_SE3, true);
}
r~