Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 34 additions & 11 deletions arch/xtensa/mmu_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,20 +201,29 @@ static void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
* Split TLB address into TLB way, entry index and VPN (with index).
* See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
*/
static void split_tlb_entry_spec(CPUState *env, uint32_t v, bool dtlb, uint32_t *vpn, uint32_t *wi, uint32_t *ei)
static bool split_tlb_entry_spec(CPUState *env, uint32_t v, bool dtlb, uint32_t *vpn, uint32_t *wi, uint32_t *ei)
{
if(xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
*wi = v & (dtlb ? 0xf : 0x7);
split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
if(*wi < (dtlb ? env->config->dtlb.nways : env->config->itlb.nways)) {
split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
return true;
} else {
return false;
}
} else {
*vpn = v & REGION_PAGE_MASK;
*wi = 0;
*ei = (v >> 29) & 0x7;
return true;
}
}

static xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env, bool dtlb, unsigned wi, unsigned ei)
{
const xtensa_tlb *tlb = dtlb ? &env->config->dtlb : &env->config->itlb;

tlib_assert(wi < tlb->nways && ei < tlb->way_size[wi]);
return dtlb ? env->dtlb[wi] + ei : env->itlb[wi] + ei;
}

Expand All @@ -224,11 +233,14 @@ static xtensa_tlb_entry *get_tlb_entry(CPUState *env, uint32_t v, bool dtlb, uin
uint32_t wi;
uint32_t ei;

split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
if(pwi) {
*pwi = wi;
if(split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
if(pwi) {
*pwi = wi;
}
return xtensa_tlb_get_entry(env, dtlb, wi, ei);
} else {
return NULL;
}
return xtensa_tlb_get_entry(env, dtlb, wi, ei);
}

static void xtensa_tlb_set_entry_mmu(const CPUState *env, xtensa_tlb_entry *entry, bool dtlb, unsigned wi, unsigned ei,
Expand Down Expand Up @@ -416,7 +428,12 @@ uint32_t HELPER(rtlb0)(CPUState *env, uint32_t v, uint32_t dtlb)
if(xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;

if(entry) {
return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
} else {
return 0;
}
} else {
return v & REGION_PAGE_MASK;
}
Expand All @@ -425,15 +442,20 @@ uint32_t HELPER(rtlb0)(CPUState *env, uint32_t v, uint32_t dtlb)
uint32_t HELPER(rtlb1)(CPUState *env, uint32_t v, uint32_t dtlb)
{
const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
return entry->paddr | entry->attr;

if(entry) {
return entry->paddr | entry->attr;
} else {
return 0;
}
}

void HELPER(itlb)(CPUState *env, uint32_t v, uint32_t dtlb)
{
if(xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
if(entry->variable && entry->asid) {
if(entry && entry->variable && entry->asid) {
tlb_flush_page(env, entry->vaddr, true);
entry->asid = 0;
}
Expand Down Expand Up @@ -471,8 +493,9 @@ void HELPER(wtlb)(CPUState *env, uint32_t p, uint32_t v, uint32_t dtlb)
uint32_t vpn;
uint32_t wi;
uint32_t ei;
split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
if(split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
}
}

/*!
Expand Down