qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@linaro.org>
To: Brian Cain <brian.cain@oss.qualcomm.com>, qemu-devel@nongnu.org
Cc: richard.henderson@linaro.org, quic_mathbern@quicinc.com,
	ale@rev.ng, anjo@rev.ng, quic_mliebel@quicinc.com,
	ltaylorsimpson@gmail.com, alex.bennee@linaro.org,
	quic_mburton@quicinc.com, sidneym@quicinc.com,
	Brian Cain <bcain@quicinc.com>,
	Michael Lambert <mlambert@quicinc.com>
Subject: Re: [PATCH 34/38] target/hexagon: Add initial MMU model
Date: Wed, 12 Mar 2025 20:20:02 +0100	[thread overview]
Message-ID: <fa38864b-8dfb-4475-9bb9-44e4a0657f68@linaro.org> (raw)
In-Reply-To: <20250301052628.1011210-35-brian.cain@oss.qualcomm.com>

On 1/3/25 06:26, Brian Cain wrote:
> From: Brian Cain <bcain@quicinc.com>
> 
> Co-authored-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> Co-authored-by: Michael Lambert <mlambert@quicinc.com>
> Co-authored-by: Sid Manning <sidneym@quicinc.com>
> Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   target/hexagon/cpu-param.h |   4 +
>   target/hexagon/cpu.h       |  13 +
>   target/hexagon/hex_mmu.h   |  30 +++
>   target/hexagon/internal.h  |   3 +
>   target/hexagon/cpu.c       |  27 +-
>   target/hexagon/hex_mmu.c   | 528 +++++++++++++++++++++++++++++++++++++
>   target/hexagon/machine.c   |  30 +++
>   target/hexagon/translate.c |   2 +-
>   target/hexagon/meson.build |   3 +-
>   9 files changed, 637 insertions(+), 3 deletions(-)
>   create mode 100644 target/hexagon/hex_mmu.h
>   create mode 100644 target/hexagon/hex_mmu.c


> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index 34c39cecd9..7ff678195d 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -28,6 +28,7 @@
>   #include "exec/gdbstub.h"
>   #include "cpu_helper.h"
>   #include "max.h"
> +#include "hex_mmu.h"
>   
>   #ifndef CONFIG_USER_ONLY
>   #include "sys_macros.h"
> @@ -283,6 +284,18 @@ static void hexagon_restore_state_to_opc(CPUState *cs,
>       cpu_env(cs)->gpr[HEX_REG_PC] = data[0];
>   }
>   
> +
> +#ifndef CONFIG_USER_ONLY
> +static void mmu_reset(CPUHexagonState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    if (cs->cpu_index == 0) {

This doesn't scale to heterogeneous emulation.

> +        memset(env->hex_tlb, 0, sizeof(*env->hex_tlb));
> +    }
> +}
> +#endif
> +
> +
>   static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
>   {
>       CPUState *cs = CPU(obj);
> @@ -310,6 +323,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
>       if (cs->cpu_index == 0) {
>           arch_set_system_reg(env, HEX_SREG_MODECTL, 0x1);
>       }
> +    mmu_reset(env);
>       arch_set_system_reg(env, HEX_SREG_HTID, cs->cpu_index);
>       memset(env->t_sreg, 0, sizeof(target_ulong) * NUM_SREGS);
>       memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS);
> @@ -341,6 +355,14 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
>           return;
>       }
>   
> +#ifndef CONFIG_USER_ONLY
> +    HexagonCPU *cpu = HEXAGON_CPU(cs);
> +    if (cpu->num_tlbs > MAX_TLB_ENTRIES) {
> +        error_setg(errp, "Number of TLBs selected is invalid");
> +        return;
> +    }
> +#endif
> +
>       gdb_register_coprocessor(cs, hexagon_hvx_gdb_read_register,
>                                hexagon_hvx_gdb_write_register,
>                                gdb_find_static_feature("hexagon-hvx.xml"), 0);
> @@ -352,9 +374,12 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
>   #endif
>   
>       qemu_init_vcpu(cs);
> +#ifndef CONFIG_USER_ONLY
> +    CPUHexagonState *env = cpu_env(cs);
> +    hex_mmu_realize(env);
> +#endif
>       cpu_reset(cs);
>   #ifndef CONFIG_USER_ONLY
> -    CPUHexagonState *env = cpu_env(cs);
>       if (cs->cpu_index == 0) {
>           env->g_sreg = g_new0(target_ulong, NUM_SREGS);
>       } else {
> diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
> new file mode 100644
> index 0000000000..54c4ba2dbf
> --- /dev/null
> +++ b/target/hexagon/hex_mmu.c
> @@ -0,0 +1,528 @@
> +/*
> + * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/main-loop.h"
> +#include "qemu/qemu-print.h"
> +#include "cpu.h"
> +#include "system/cpus.h"
> +#include "internal.h"
> +#include "exec/exec-all.h"
> +#include "hex_mmu.h"
> +#include "macros.h"
> +#include "sys_macros.h"
> +#include "reg_fields.h"
> +
> +#define GET_TLB_FIELD(ENTRY, FIELD)                               \
> +    ((uint64_t)fEXTRACTU_BITS(ENTRY, reg_field_info[FIELD].width, \
> +                              reg_field_info[FIELD].offset))
> +
> +/* PPD (physical page descriptor) */
> +static inline uint64_t GET_PPD(uint64_t entry)
> +{
> +    return GET_TLB_FIELD(entry, PTE_PPD) |
> +        (GET_TLB_FIELD(entry, PTE_PA35) << reg_field_info[PTE_PPD].width);
> +}
> +
> +#define NO_ASID      (1 << 8)
> +
> +typedef enum {
> +    PGSIZE_4K,
> +    PGSIZE_16K,
> +    PGSIZE_64K,
> +    PGSIZE_256K,
> +    PGSIZE_1M,
> +    PGSIZE_4M,
> +    PGSIZE_16M,
> +    PGSIZE_64M,
> +    PGSIZE_256M,
> +    PGSIZE_1G,
> +    NUM_PGSIZE_TYPES

Is NUM_PGSIZE_TYPES part of the enum?

> +} tlb_pgsize_t;
> +
> +static const char *pgsize_str[NUM_PGSIZE_TYPES] = {
> +    "4K",
> +    "16K",
> +    "64K",
> +    "256K",
> +    "1M",
> +    "4M",
> +    "16M",
> +    "64M",
> +    "256M",
> +    "1G",
> +};
> +
> +#define INVALID_MASK 0xffffffffLL
> +
> +static const uint64_t encmask_2_mask[] = {
> +    0x0fffLL,                           /* 4k,   0000 */
> +    0x3fffLL,                           /* 16k,  0001 */
> +    0xffffLL,                           /* 64k,  0010 */
> +    0x3ffffLL,                          /* 256k, 0011 */
> +    0xfffffLL,                          /* 1m,   0100 */
> +    0x3fffffLL,                         /* 4m,   0101 */
> +    0xffffffLL,                         /* 16m,  0110 */
> +    0x3ffffffLL,                        /* 64m,  0111 */
> +    0xfffffffLL,                        /* 256m, 1000 */
> +    0x3fffffffLL,                       /* 1g,   1001 */
> +    INVALID_MASK,                      /* RSVD, 0111 */
> +};
> +
> +/*
> + * @return the page size type from @a entry.
> + */
> +static inline tlb_pgsize_t hex_tlb_pgsize_type(uint64_t entry)
> +{
> +    if (entry == 0) {
> +        qemu_log_mask(CPU_LOG_MMU, "%s: Supplied TLB entry was 0!\n", __func__);
> +        return 0;
> +    }
> +    tlb_pgsize_t size = ctz64(entry);
> +    g_assert(size < NUM_PGSIZE_TYPES);
> +    return size;
> +}
> +
> +/*
> + * @return the page size of @a entry, in bytes.
> + */
> +static inline uint64_t hex_tlb_page_size_bytes(uint64_t entry)
> +{
> +    return 1ull << (TARGET_PAGE_BITS + 2 * hex_tlb_pgsize_type(entry));
> +}
> +
> +static inline uint64_t hex_tlb_phys_page_num(uint64_t entry)
> +{
> +    uint32_t ppd = GET_PPD(entry);
> +    return ppd >> 1;
> +}
> +
> +static inline uint64_t hex_tlb_phys_addr(uint64_t entry)
> +{
> +    uint64_t pagemask = encmask_2_mask[hex_tlb_pgsize_type(entry)];
> +    uint64_t pagenum = hex_tlb_phys_page_num(entry);
> +    uint64_t PA = (pagenum << TARGET_PAGE_BITS) & (~pagemask);
> +    return PA;
> +}
> +
> +static inline uint64_t hex_tlb_virt_addr(uint64_t entry)
> +{
> +    return (uint64_t)GET_TLB_FIELD(entry, PTE_VPN) << TARGET_PAGE_BITS;

return vaddr type?

> +}
> +
> +static bool hex_dump_mmu_entry(FILE *f, uint64_t entry)
> +{
> +    if (GET_TLB_FIELD(entry, PTE_V)) {
> +        fprintf(f, "0x%016" PRIx64 ": ", entry);
> +        uint64_t PA = hex_tlb_phys_addr(entry);
> +        uint64_t VA = hex_tlb_virt_addr(entry);
> +        fprintf(f, "V:%" PRId64 " G:%" PRId64 " A1:%" PRId64 " A0:%" PRId64,
> +                GET_TLB_FIELD(entry, PTE_V), GET_TLB_FIELD(entry, PTE_G),
> +                GET_TLB_FIELD(entry, PTE_ATR1), GET_TLB_FIELD(entry, PTE_ATR0));
> +        fprintf(f, " ASID:0x%02" PRIx64 " VA:0x%08" PRIx64,
> +                GET_TLB_FIELD(entry, PTE_ASID), VA);
> +        fprintf(f,
> +                " X:%" PRId64 " W:%" PRId64 " R:%" PRId64 " U:%" PRId64
> +                " C:%" PRId64,
> +                GET_TLB_FIELD(entry, PTE_X), GET_TLB_FIELD(entry, PTE_W),
> +                GET_TLB_FIELD(entry, PTE_R), GET_TLB_FIELD(entry, PTE_U),
> +                GET_TLB_FIELD(entry, PTE_C));
> +        fprintf(f, " PA:0x%09" PRIx64 " SZ:%s (0x%" PRIx64 ")", PA,
> +                pgsize_str[hex_tlb_pgsize_type(entry)],
> +                hex_tlb_page_size_bytes(entry));
> +        fprintf(f, "\n");
> +        return true;
> +    }
> +
> +    /* Not valid */
> +    return false;
> +}
> +
> +void dump_mmu(CPUHexagonState *env)
> +{
> +    int i;
> +
> +    HexagonCPU *cpu = env_archcpu(env);
> +    for (i = 0; i < cpu->num_tlbs; i++) {
> +        uint64_t entry = env->hex_tlb->entries[i];
> +        if (GET_TLB_FIELD(entry, PTE_V)) {
> +            qemu_printf("0x%016" PRIx64 ": ", entry);
> +            uint64_t PA = hex_tlb_phys_addr(entry);
> +            uint64_t VA = hex_tlb_virt_addr(entry);
> +            qemu_printf(
> +                "V:%" PRId64 " G:%" PRId64 " A1:%" PRId64 " A0:%" PRId64,
> +                GET_TLB_FIELD(entry, PTE_V), GET_TLB_FIELD(entry, PTE_G),
> +                GET_TLB_FIELD(entry, PTE_ATR1), GET_TLB_FIELD(entry, PTE_ATR0));
> +            qemu_printf(" ASID:0x%02" PRIx64 " VA:0x%08" PRIx64,
> +                        GET_TLB_FIELD(entry, PTE_ASID), VA);
> +            qemu_printf(
> +                " X:%" PRId64 " W:%" PRId64 " R:%" PRId64 " U:%" PRId64
> +                " C:%" PRId64,
> +                GET_TLB_FIELD(entry, PTE_X), GET_TLB_FIELD(entry, PTE_W),
> +                GET_TLB_FIELD(entry, PTE_R), GET_TLB_FIELD(entry, PTE_U),
> +                GET_TLB_FIELD(entry, PTE_C));
> +            qemu_printf(" PA:0x%09" PRIx64 " SZ:%s (0x%" PRIx64 ")", PA,
> +                        pgsize_str[hex_tlb_pgsize_type(entry)],
> +                        hex_tlb_page_size_bytes(entry));
> +            qemu_printf("\n");
> +        }
> +    }
> +}
> +
> +static inline void hex_log_tlbw(uint32_t index, uint64_t entry)
> +{
> +    if (qemu_loglevel_mask(CPU_LOG_MMU)) {
> +        if (qemu_log_enabled()) {
> +            FILE *logfile = qemu_log_trylock();
> +            if (logfile) {
> +                fprintf(logfile, "tlbw[%03d]: ", index);
> +                if (!hex_dump_mmu_entry(logfile, entry)) {
> +                    fprintf(logfile, "invalid\n");
> +                }
> +                qemu_log_unlock(logfile);
> +            }
> +        }
> +    }
> +}
> +
> +void hex_tlbw(CPUHexagonState *env, uint32_t index, uint64_t value)
> +{
> +    uint32_t myidx = fTLB_NONPOW2WRAP(fTLB_IDXMASK(index));
> +    bool old_entry_valid = GET_TLB_FIELD(env->hex_tlb->entries[myidx], PTE_V);
> +    if (old_entry_valid && hexagon_cpu_mmu_enabled(env)) {
> +        CPUState *cs = env_cpu(env);
> +
> +        tlb_flush(cs);
> +    }
> +    env->hex_tlb->entries[myidx] = (value);
> +    hex_log_tlbw(myidx, value);
> +}
> +
> +void hex_mmu_realize(CPUHexagonState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    if (cs->cpu_index == 0) {

Problem with heterogeneous emulation.

> +        env->hex_tlb = g_malloc0(sizeof(CPUHexagonTLBContext));
> +    } else {
> +        CPUState *cpu0_s = NULL;
> +        CPUHexagonState *env0 = NULL;
> +        CPU_FOREACH(cpu0_s) {
> +            assert(cpu0_s->cpu_index == 0);
> +            env0 = &(HEXAGON_CPU(cpu0_s)->env);
> +            break;
> +        }
> +        env->hex_tlb = env0->hex_tlb;
> +    }
> +}
> +
> +void hex_mmu_on(CPUHexagonState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    qemu_log_mask(CPU_LOG_MMU, "Hexagon MMU turned on!\n");
> +    tlb_flush(cs);
> +}
> +
> +void hex_mmu_off(CPUHexagonState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    qemu_log_mask(CPU_LOG_MMU, "Hexagon MMU turned off!\n");
> +    tlb_flush(cs);
> +}
> +
> +void hex_mmu_mode_change(CPUHexagonState *env)
> +{
> +    qemu_log_mask(CPU_LOG_MMU, "Hexagon mode change!\n");
> +    CPUState *cs = env_cpu(env);
> +    tlb_flush(cs);
> +}
> +
> +static inline bool hex_tlb_entry_match_noperm(uint64_t entry, uint32_t asid,
> +                                              uint64_t VA)
> +{
> +    if (GET_TLB_FIELD(entry, PTE_V)) {
> +        if (GET_TLB_FIELD(entry, PTE_G)) {
> +            /* Global entry - ingnore ASID */
> +        } else if (asid != NO_ASID) {
> +            uint32_t tlb_asid = GET_TLB_FIELD(entry, PTE_ASID);
> +            if (tlb_asid != asid) {
> +                return false;
> +            }
> +        }
> +
> +        uint64_t page_size = hex_tlb_page_size_bytes(entry);
> +        uint64_t page_start =
> +            ROUND_DOWN(hex_tlb_virt_addr(entry), page_size);
> +        if (page_start <= VA && VA < page_start + page_size) {
> +            return true;
> +        }
> +    }
> +    return false;
> +}
> +
> +static inline void hex_tlb_entry_get_perm(CPUHexagonState *env, uint64_t entry,
> +                                          MMUAccessType access_type,
> +                                          int mmu_idx, int *prot,
> +                                          int32_t *excp)
> +{
> +    g_assert_not_reached();
> +}
> +
> +static inline bool hex_tlb_entry_match(CPUHexagonState *env, uint64_t entry,
> +                                       uint8_t asid, target_ulong VA,
> +                                       MMUAccessType access_type, hwaddr *PA,
> +                                       int *prot, int *size, int32_t *excp,
> +                                       int mmu_idx)
> +{
> +    if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
> +        hex_tlb_entry_get_perm(env, entry, access_type, mmu_idx, prot, excp);
> +        *PA = hex_tlb_phys_addr(entry);
> +        *size = hex_tlb_page_size_bytes(entry);
> +        return true;
> +    }
> +    return false;
> +}
> +
> +bool hex_tlb_find_match(CPUHexagonState *env, target_ulong VA,
> +                        MMUAccessType access_type, hwaddr *PA, int *prot,
> +                        int *size, int32_t *excp, int mmu_idx)
> +{
> +    *PA = 0;
> +    *prot = 0;
> +    *size = 0;
> +    *excp = 0;
> +    uint32_t ssr = arch_get_system_reg(env, HEX_SREG_SSR);
> +    uint8_t asid = GET_SSR_FIELD(SSR_ASID, ssr);
> +    int i;
> +    HexagonCPU *cpu = env_archcpu(env);
> +    for (i = 0; i < cpu->num_tlbs; i++) {
> +        uint64_t entry = env->hex_tlb->entries[i];
> +        if (hex_tlb_entry_match(env, entry, asid, VA, access_type, PA, prot,
> +                                size, excp, mmu_idx)) {
> +            return true;
> +        }
> +    }
> +    return false;
> +}
> +
> +static uint32_t hex_tlb_lookup_by_asid(CPUHexagonState *env, uint32_t asid,
> +                                       uint32_t VA)
> +{
> +    g_assert_not_reached();
> +}
> +
> +/* Called from tlbp instruction */
> +uint32_t hex_tlb_lookup(CPUHexagonState *env, uint32_t ssr, uint32_t VA)
> +{
> +    return hex_tlb_lookup_by_asid(env, GET_SSR_FIELD(SSR_ASID, ssr), VA);
> +}
> +
> +static bool hex_tlb_is_match(CPUHexagonState *env,
> +                             uint64_t entry1, uint64_t entry2,
> +                             bool consider_gbit)
> +{
> +    bool valid1 = GET_TLB_FIELD(entry1, PTE_V);
> +    bool valid2 = GET_TLB_FIELD(entry2, PTE_V);
> +    uint64_t size1 = hex_tlb_page_size_bytes(entry1);
> +    uint64_t vaddr1 = ROUND_DOWN(hex_tlb_virt_addr(entry1), size1);
> +    uint64_t size2 = hex_tlb_page_size_bytes(entry2);
> +    uint64_t vaddr2 = ROUND_DOWN(hex_tlb_virt_addr(entry2), size2);
> +    int asid1 = GET_TLB_FIELD(entry1, PTE_ASID);
> +    int asid2 = GET_TLB_FIELD(entry2, PTE_ASID);
> +    bool gbit1 = GET_TLB_FIELD(entry1, PTE_G);
> +    bool gbit2 = GET_TLB_FIELD(entry2, PTE_G);
> +
> +    if (!valid1 || !valid2) {
> +        return false;
> +    }
> +
> +    if (((vaddr1 <= vaddr2) && (vaddr2 < (vaddr1 + size1))) ||
> +        ((vaddr2 <= vaddr1) && (vaddr1 < (vaddr2 + size2)))) {
> +        if (asid1 == asid2) {
> +            return true;
> +        }
> +        if ((consider_gbit && gbit1) || gbit2) {
> +            return true;
> +        }
> +    }
> +    return false;
> +}
> +
> +/*
> + * Return codes:
> + * 0 or positive             index of match
> + * -1                        multiple matches
> + * -2                        no match
> + */
> +int hex_tlb_check_overlap(CPUHexagonState *env, uint64_t entry, uint64_t index)
> +{
> +    int matches = 0;
> +    int last_match = 0;
> +    int i;
> +
> +    HexagonCPU *cpu = env_archcpu(env);
> +    for (i = 0; i < cpu->num_tlbs; i++) {
> +        if (hex_tlb_is_match(env, entry, env->hex_tlb->entries[i], false)) {
> +            matches++;
> +            last_match = i;
> +        }
> +    }
> +
> +    if (matches == 1) {
> +        return last_match;
> +    }
> +    if (matches == 0) {
> +        return -2;
> +    }
> +    return -1;
> +}
> +
> +static inline void print_thread(const char *str, CPUState *cs)
> +{
> +    g_assert(bql_locked());
> +    CPUHexagonState *thread = cpu_env(cs);
> +    bool is_stopped = cpu_is_stopped(cs);
> +    int exe_mode = get_exe_mode(thread);
> +    hex_lock_state_t lock_state = thread->tlb_lock_state;
> +    qemu_log_mask(CPU_LOG_MMU,
> +           "%s: threadId = %d: %s, exe_mode = %s, tlb_lock_state = %s\n",
> +           str,
> +           thread->threadId,
> +           is_stopped ? "stopped" : "running",
> +           exe_mode == HEX_EXE_MODE_OFF ? "off" :
> +           exe_mode == HEX_EXE_MODE_RUN ? "run" :
> +           exe_mode == HEX_EXE_MODE_WAIT ? "wait" :
> +           exe_mode == HEX_EXE_MODE_DEBUG ? "debug" :
> +           "unknown",
> +           lock_state == HEX_LOCK_UNLOCKED ? "unlocked" :
> +           lock_state == HEX_LOCK_WAITING ? "waiting" :
> +           lock_state == HEX_LOCK_OWNER ? "owner" :
> +           "unknown");
> +}
> +
> +static inline void print_thread_states(const char *str)
> +{
> +    CPUState *cs;
> +    CPU_FOREACH(cs) {

Ditto heterogeneous emulation.

> +        print_thread(str, cs);
> +    }
> +}
> +
> +void hex_tlb_lock(CPUHexagonState *env)
> +{
> +    qemu_log_mask(CPU_LOG_MMU, "hex_tlb_lock: %d\n", env->threadId);
> +    BQL_LOCK_GUARD();
> +    g_assert((env->tlb_lock_count == 0) || (env->tlb_lock_count == 1));
> +
> +    uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
> +    uint8_t tlb_lock = GET_SYSCFG_FIELD(SYSCFG_TLBLOCK, syscfg);
> +    if (tlb_lock) {
> +        if (env->tlb_lock_state == HEX_LOCK_QUEUED) {
> +            env->next_PC += 4;
> +            env->tlb_lock_count++;
> +            env->tlb_lock_state = HEX_LOCK_OWNER;
> +            SET_SYSCFG_FIELD(env, SYSCFG_TLBLOCK, 1);
> +            return;
> +        }
> +        if (env->tlb_lock_state == HEX_LOCK_OWNER) {
> +            qemu_log_mask(CPU_LOG_MMU | LOG_GUEST_ERROR,
> +                          "Double tlblock at PC: 0x%x, thread may hang\n",
> +                          env->next_PC);
> +            env->next_PC += 4;
> +            CPUState *cs = env_cpu(env);
> +            cpu_interrupt(cs, CPU_INTERRUPT_HALT);
> +            return;
> +        }
> +        env->tlb_lock_state = HEX_LOCK_WAITING;
> +        CPUState *cs = env_cpu(env);
> +        cpu_interrupt(cs, CPU_INTERRUPT_HALT);
> +    } else {
> +        env->next_PC += 4;
> +        env->tlb_lock_count++;
> +        env->tlb_lock_state = HEX_LOCK_OWNER;
> +        SET_SYSCFG_FIELD(env, SYSCFG_TLBLOCK, 1);
> +    }
> +
> +    if (qemu_loglevel_mask(CPU_LOG_MMU)) {
> +        qemu_log_mask(CPU_LOG_MMU, "Threads after hex_tlb_lock:\n");
> +        print_thread_states("\tThread");
> +    }
> +}
> +
> +void hex_tlb_unlock(CPUHexagonState *env)
> +{
> +    BQL_LOCK_GUARD();
> +    g_assert((env->tlb_lock_count == 0) || (env->tlb_lock_count == 1));
> +
> +    /* Nothing to do if the TLB isn't locked by this thread */
> +    uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
> +    uint8_t tlb_lock = GET_SYSCFG_FIELD(SYSCFG_TLBLOCK, syscfg);
> +    if ((tlb_lock == 0) ||
> +        (env->tlb_lock_state != HEX_LOCK_OWNER)) {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "thread %d attempted to tlbunlock without having the "
> +                      "lock, tlb_lock state = %d\n",
> +                      env->threadId, env->tlb_lock_state);
> +        g_assert(env->tlb_lock_state != HEX_LOCK_WAITING);
> +        return;
> +    }
> +
> +    env->tlb_lock_count--;
> +    env->tlb_lock_state = HEX_LOCK_UNLOCKED;
> +    SET_SYSCFG_FIELD(env, SYSCFG_TLBLOCK, 0);
> +
> +    /* Look for a thread to unlock */
> +    unsigned int this_threadId = env->threadId;
> +    CPUHexagonState *unlock_thread = NULL;
> +    CPUState *cs;
> +    CPU_FOREACH(cs) {

Ditto.

> +        CPUHexagonState *thread = cpu_env(cs);
> +
> +        /*
> +         * The hardware implements round-robin fairness, so we look for threads
> +         * starting at env->threadId + 1 and incrementing modulo the number of
> +         * threads.
> +         *
> +         * To implement this, we check if thread is a earlier in the modulo
> +         * sequence than unlock_thread.
> +         *     if unlock thread is higher than this thread
> +         *         thread must be between this thread and unlock_thread
> +         *     else
> +         *         thread higher than this thread is ahead of unlock_thread
> +         *         thread must be lower then unlock thread
> +         */
> +        if (thread->tlb_lock_state == HEX_LOCK_WAITING) {
> +            if (!unlock_thread) {
> +                unlock_thread = thread;
> +            } else if (unlock_thread->threadId > this_threadId) {
> +                if (this_threadId < thread->threadId &&
> +                    thread->threadId < unlock_thread->threadId) {
> +                    unlock_thread = thread;
> +                }
> +            } else {
> +                if (thread->threadId > this_threadId) {
> +                    unlock_thread = thread;
> +                }
> +                if (thread->threadId < unlock_thread->threadId) {
> +                    unlock_thread = thread;
> +                }
> +            }
> +        }
> +    }


  parent reply	other threads:[~2025-03-12 19:20 UTC|newest]

Thread overview: 121+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-01  5:25 [PATCH 00/38] hexagon system emu, part 1/3 Brian Cain
2025-03-01  5:25 ` [PATCH 01/38] docs: Add hexagon sysemu docs Brian Cain
2025-03-05 19:29   ` ltaylorsimpson
2025-03-01  5:25 ` [PATCH 02/38] docs/system: Add hexagon CPU emulation Brian Cain
2025-03-05 19:36   ` ltaylorsimpson
2025-03-05 20:12     ` Brian Cain
2025-03-05 21:21       ` ltaylorsimpson
2025-03-05 21:28         ` Brian Cain
2025-03-01  5:25 ` [PATCH 03/38] target/hexagon: Add System/Guest register definitions Brian Cain
2025-03-06 20:54   ` ltaylorsimpson
2025-04-16 17:54   ` ltaylorsimpson
2025-04-16 19:43     ` Brian Cain
2025-04-16 22:02       ` ltaylorsimpson
2025-09-02  0:17         ` Brian Cain
2025-03-01  5:25 ` [PATCH 04/38] target/hexagon: Make gen_exception_end_tb non-static Brian Cain
2025-03-06 20:55   ` ltaylorsimpson
2025-03-01  5:25 ` [PATCH 05/38] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags() Brian Cain via
2025-03-06 21:07   ` ltaylorsimpson
2025-03-01  5:25 ` [PATCH 06/38] target/hexagon: Add privilege check, use tag_ignore() Brian Cain
2025-03-06 21:11   ` ltaylorsimpson
2025-03-06 22:01   ` Richard Henderson
2025-09-02  0:24     ` Brian Cain
2025-03-01  5:25 ` [PATCH 07/38] target/hexagon: Add a placeholder fp exception Brian Cain
2025-03-06 21:22   ` ltaylorsimpson
2025-03-01  5:25 ` [PATCH 08/38] target/hexagon: Add guest, system reg number defs Brian Cain
2025-03-06 21:30   ` ltaylorsimpson
2025-03-08  0:35     ` Sid Manning
2025-09-02  0:25     ` Brian Cain
2025-03-01  5:25 ` [PATCH 09/38] target/hexagon: Add guest, system reg number state Brian Cain
2025-03-06 21:32   ` ltaylorsimpson
2025-03-12 19:15   ` Philippe Mathieu-Daudé
2025-09-02  0:27     ` Brian Cain
2025-03-01  5:26 ` [PATCH 10/38] target/hexagon: Add TCG values for sreg, greg Brian Cain
2025-03-06 21:38   ` ltaylorsimpson
2025-09-02  0:28     ` Brian Cain
2025-03-01  5:26 ` [PATCH 11/38] target/hexagon: Add guest/sys reg writes to DisasContext Brian Cain
2025-03-06 21:40   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 12/38] target/hexagon: Add imported macro, attr defs for sysemu Brian Cain
2025-03-07 19:01   ` ltaylorsimpson
2025-09-02  0:36     ` Brian Cain
2025-03-01  5:26 ` [PATCH 13/38] target/hexagon: Define DCache states Brian Cain
2025-03-07 19:03   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 14/38] target/hexagon: Add new macro definitions for sysemu Brian Cain
2025-03-07 19:35   ` ltaylorsimpson
2025-09-02  0:38     ` Brian Cain
2025-03-01  5:26 ` [PATCH 15/38] target/hexagon: Add handlers for guest/sysreg r/w Brian Cain
2025-03-07 19:46   ` ltaylorsimpson
2025-09-02  0:40     ` Brian Cain
2025-03-01  5:26 ` [PATCH 16/38] target/hexagon: Add placeholder greg/sreg r/w helpers Brian Cain
2025-03-07 20:45   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 17/38] target/hexagon: Add vmstate representation Brian Cain
2025-03-07 21:19   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 18/38] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env() Brian Cain
2025-03-07 21:20   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 19/38] target/hexagon: Define register fields for system regs Brian Cain
2025-03-07 21:21   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 20/38] target/hexagon: Implement do_raise_exception() Brian Cain
2025-03-07 21:28   ` ltaylorsimpson
2025-09-02  0:41     ` Brian Cain
2025-03-01  5:26 ` [PATCH 21/38] target/hexagon: Add system reg insns Brian Cain
2025-03-08  1:32   ` ltaylorsimpson
2025-09-02  0:44     ` Brian Cain
2025-03-01  5:26 ` [PATCH 22/38] target/hexagon: Add sysemu TCG overrides Brian Cain
2025-03-08  1:43   ` ltaylorsimpson
2025-09-02  0:46     ` Brian Cain
2025-03-01  5:26 ` [PATCH 23/38] target/hexagon: Add implicit attributes to sysemu macros Brian Cain
2025-03-11 22:30   ` ltaylorsimpson
2025-09-02  0:47     ` Brian Cain
2025-03-01  5:26 ` [PATCH 24/38] target/hexagon: Add TCG overrides for int handler insts Brian Cain
2025-03-08  1:46   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 25/38] target/hexagon: Add TCG overrides for thread ctl Brian Cain
2025-03-08  1:47   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 26/38] target/hexagon: Add TCG overrides for rte, nmi Brian Cain
2025-03-11 22:33   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 27/38] target/hexagon: Add sreg_{read,write} helpers Brian Cain
2025-03-11 23:22   ` ltaylorsimpson
2025-09-02  0:53     ` Brian Cain
2025-03-01  5:26 ` [PATCH 28/38] target/hexagon: Initialize htid, modectl regs Brian Cain
2025-03-11 23:26   ` ltaylorsimpson
2025-03-12 14:02     ` Sid Manning
2025-03-12 19:19   ` Philippe Mathieu-Daudé
2025-03-12 23:10     ` Brian Cain
2025-03-12 23:40       ` Philippe Mathieu-Daudé
2025-03-13 18:47         ` ltaylorsimpson
2025-03-13 19:06           ` Richard Henderson
2025-03-19 16:08             ` Sid Manning
2025-03-20 15:34               ` Richard Henderson
2025-03-20 17:38                 ` Sid Manning
2025-09-02  0:56                   ` Brian Cain
2025-03-01  5:26 ` [PATCH 29/38] target/hexagon: Add locks, id, next_PC to state Brian Cain
2025-03-11 23:33   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 30/38] target/hexagon: Add a TLB count property Brian Cain
2025-03-11 23:41   ` ltaylorsimpson
2025-03-12 14:01     ` Sid Manning
2025-03-01  5:26 ` [PATCH 31/38] target/hexagon: Add {TLB, k0}lock, cause code, wait_next_pc Brian Cain via
2025-03-11 23:44   ` ltaylorsimpson
2025-03-12 16:58   ` [PATCH 31/38] target/hexagon: Add {TLB,k0}lock, " Sid Manning
2025-03-01  5:26 ` [PATCH 32/38] target/hexagon: Add stubs for modify_ssr/get_exe_mode Brian Cain
2025-03-11 23:43   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 33/38] target/hexagon: Add gdb support for sys regs Brian Cain
2025-03-12 16:27   ` ltaylorsimpson
2025-03-12 19:10     ` Sid Manning
2025-03-12 19:27       ` Sid Manning
2025-03-12 19:46         ` Matheus Tavares Bernardino
2025-09-02  1:15   ` Brian Cain
2025-03-01  5:26 ` [PATCH 34/38] target/hexagon: Add initial MMU model Brian Cain
2025-03-12 17:04   ` ltaylorsimpson
2025-09-02  1:20     ` Brian Cain
2025-03-12 19:20   ` Philippe Mathieu-Daudé [this message]
2025-03-12 21:15     ` Sid Manning
2025-03-12 23:32       ` Philippe Mathieu-Daudé
2025-03-01  5:26 ` [PATCH 35/38] target/hexagon: Add IRQ events Brian Cain
2025-03-12 17:06   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 36/38] target/hexagon: Add clear_wait_mode() definition Brian Cain
2025-03-12 17:08   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 37/38] target/hexagon: Define f{S,G}ET_FIELD macros Brian Cain
2025-03-12 17:11   ` ltaylorsimpson
2025-03-01  5:26 ` [PATCH 38/38] target/hexagon: Add hex_interrupts support Brian Cain
2025-03-12 17:32   ` ltaylorsimpson
2025-09-02  1:22     ` Brian Cain
     [not found] <011101db9370_ddebf410_99c3dc30_@gmail.com>
2025-03-12 17:12 ` [PATCH 34/38] target/hexagon: Add initial MMU model Matheus Tavares Bernardino

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fa38864b-8dfb-4475-9bb9-44e4a0657f68@linaro.org \
    --to=philmd@linaro.org \
    --cc=ale@rev.ng \
    --cc=alex.bennee@linaro.org \
    --cc=anjo@rev.ng \
    --cc=bcain@quicinc.com \
    --cc=brian.cain@oss.qualcomm.com \
    --cc=ltaylorsimpson@gmail.com \
    --cc=mlambert@quicinc.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quic_mathbern@quicinc.com \
    --cc=quic_mburton@quicinc.com \
    --cc=quic_mliebel@quicinc.com \
    --cc=richard.henderson@linaro.org \
    --cc=sidneym@quicinc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).