qemu-devel
[Top][All Lists]
Advanced

[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~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]