Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mips/tlb.c
Show All 34 Lines | |||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <machine/pte.h> | #include <machine/pte.h> | ||||
#include <machine/tlb.h> | #include <machine/tlb.h> | ||||
#include "opt_vm.h" | |||||
jmallett: Necessary? | |||||
#if defined(CPU_CNMIPS) | #if defined(CPU_CNMIPS) | ||||
#define MIPS_MAX_TLB_ENTRIES 128 | #define MIPS_MAX_TLB_ENTRIES 128 | ||||
#elif defined(CPU_NLM) | #elif defined(CPU_NLM) | ||||
#define MIPS_MAX_TLB_ENTRIES (2048 + 128) | #define MIPS_MAX_TLB_ENTRIES (2048 + 128) | ||||
#elif defined(CPU_CHERI) | |||||
#define MIPS_MAX_TLB_ENTRIES 144 | |||||
#else | #else | ||||
#define MIPS_MAX_TLB_ENTRIES 64 | #define MIPS_MAX_TLB_ENTRIES 64 | ||||
#endif | #endif | ||||
struct tlb_state { | struct tlb_state { | ||||
unsigned wired; | unsigned wired; | ||||
struct tlb_entry { | struct tlb_entry { | ||||
register_t entryhi; | register_t entryhi; | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
static void tlb_invalidate_one(unsigned); | static void tlb_invalidate_one(unsigned); | ||||
void | void | ||||
tlb_insert_wired(unsigned i, vm_offset_t va, pt_entry_t pte0, pt_entry_t pte1) | tlb_insert_wired(unsigned i, vm_offset_t va, pt_entry_t pte0, pt_entry_t pte1) | ||||
{ | { | ||||
register_t asid; | register_t asid; | ||||
register_t s; | register_t s; | ||||
uint32_t pagemask; | |||||
unsigned long mask, size; | |||||
va &= ~PAGE_MASK; | KASSERT((TLBLO_PTE_TO_IDX(pte0) == TLBLO_PTE_TO_IDX(pte1)), | ||||
("%s: pte0 and pte1 page sizes don't match", __func__)); | |||||
/* Compute the page mask and size. */ | |||||
pagemask = TLBLO_PTE_TO_MASK(pte0); | |||||
mask = (unsigned long)pagemask | PAGE_MASK; /* OR it with lower 12 bits */ | |||||
size = mask + 1; | |||||
va &= ~mask; | |||||
s = intr_disable(); | s = intr_disable(); | ||||
asid = mips_rd_entryhi() & TLBHI_ASID_MASK; | asid = mips_rd_entryhi() & TLBHI_ASID_MASK; | ||||
mips_wr_index(i); | mips_wr_index(i); | ||||
mips_wr_pagemask(0); | mips_wr_pagemask(pagemask); | ||||
mips_wr_entryhi(TLBHI_ENTRY(va, 0)); | mips_wr_entryhi(TLBHI_ENTRY(va, 0)); | ||||
mips_wr_entrylo0(pte0); | mips_wr_entrylo0(pte0); | ||||
mips_wr_entrylo1(pte1); | mips_wr_entrylo1(pte1); | ||||
tlb_write_indexed(); | tlb_write_indexed(); | ||||
mips_wr_entryhi(asid); | mips_wr_entryhi(asid); | ||||
mips_wr_pagemask(0); | |||||
intr_restore(s); | intr_restore(s); | ||||
} | } | ||||
void | void | ||||
tlb_invalidate_address(struct pmap *pmap, vm_offset_t va) | tlb_invalidate_address(struct pmap *pmap, vm_offset_t va) | ||||
{ | { | ||||
register_t asid; | register_t asid; | ||||
register_t s; | register_t s; | ||||
int i; | int i; | ||||
va &= ~PAGE_MASK; | va &= ~PAGE_MASK; | ||||
s = intr_disable(); | s = intr_disable(); | ||||
asid = mips_rd_entryhi() & TLBHI_ASID_MASK; | asid = mips_rd_entryhi() & TLBHI_ASID_MASK; | ||||
mips_wr_pagemask(0); | mips_wr_pagemask(0); | ||||
mips_wr_entryhi(TLBHI_ENTRY(va, pmap_asid(pmap))); | mips_wr_entryhi(TLBHI_ENTRY(va, pmap_asid(pmap))); | ||||
tlb_probe(); | tlb_probe(); | ||||
i = mips_rd_index(); | i = mips_rd_index(); | ||||
if (i >= 0) | if (i >= 0) | ||||
tlb_invalidate_one(i); | tlb_invalidate_one(i); | ||||
mips_wr_entryhi(asid); | mips_wr_entryhi(asid); | ||||
intr_restore(s); | intr_restore(s); | ||||
} | } | ||||
void | void | ||||
tlb_invalidate_all(void) | tlb_invalidate_all(void) | ||||
{ | { | ||||
register_t asid; | register_t asid; | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void | void | ||||
tlb_update(struct pmap *pmap, vm_offset_t va, pt_entry_t pte) | tlb_update(struct pmap *pmap, vm_offset_t va, pt_entry_t pte) | ||||
{ | { | ||||
register_t asid; | register_t asid; | ||||
register_t s; | register_t s; | ||||
int i; | int i; | ||||
uint32_t pagemask; | |||||
unsigned long mask, size; | |||||
pt_entry_t pte0, pte1; | |||||
va &= ~PAGE_MASK; | /* Compute the page mask and size. */ | ||||
pagemask = TLBLO_PTE_TO_MASK(pte); | |||||
mask = (unsigned long)pagemask | PAGE_MASK; /* OR it with lower 12 bits */ | |||||
size = mask + 1; | |||||
va &= ~mask; | |||||
pte &= ~TLBLO_SWBITS_MASK; | pte &= ~TLBLO_SWBITS_MASK; | ||||
s = intr_disable(); | s = intr_disable(); | ||||
asid = mips_rd_entryhi() & TLBHI_ASID_MASK; | asid = mips_rd_entryhi() & TLBHI_ASID_MASK; | ||||
mips_wr_pagemask(0); | mips_wr_pagemask(pagemask); | ||||
mips_wr_entryhi(TLBHI_ENTRY(va, pmap_asid(pmap))); | mips_wr_entryhi(TLBHI_ENTRY(va, pmap_asid(pmap))); | ||||
tlb_probe(); | tlb_probe(); | ||||
i = mips_rd_index(); | i = mips_rd_index(); | ||||
if (i >= 0) { | if (i >= 0) { | ||||
tlb_read(); | tlb_read(); | ||||
pte0 = mips_rd_entrylo0(); | |||||
pte1 = mips_rd_entrylo1(); | |||||
KASSERT((TLBLO_PTE_TO_IDX(pte) == TLBLO_PTE_TO_IDX(pte0) && | |||||
TLBLO_PTE_TO_IDX(pte) == TLBLO_PTE_TO_IDX(pte1)), | |||||
("%s: pte, pte0 and pte1 page sizes don't match", __func__)); | |||||
if ((va & PAGE_SIZE) == 0) { | if ((va & size) == 0) { | ||||
mips_wr_entrylo0(pte); | mips_wr_entrylo0(pte); | ||||
if (pagemask & ~PAGE_MASK) { | |||||
/* Superpage */ | |||||
pte1 = (pte1 & ~(PTE_VR | PTE_D)) | (pte & (PTE_VR | PTE_D)); | |||||
mips_wr_entrylo1(pte1); | |||||
} | |||||
} else { | } else { | ||||
mips_wr_entrylo1(pte); | mips_wr_entrylo1(pte); | ||||
if (pagemask & ~PAGE_MASK) { | |||||
/* Superpage */ | |||||
pte0 = (pte0 & ~(PTE_VR | PTE_D)) | (pte & (PTE_VR | PTE_D)); | |||||
mips_wr_entrylo0(pte0); | |||||
} | } | ||||
} | |||||
tlb_write_indexed(); | tlb_write_indexed(); | ||||
} | } | ||||
mips_wr_entryhi(asid); | mips_wr_entryhi(asid); | ||||
mips_wr_pagemask(0); | |||||
intr_restore(s); | intr_restore(s); | ||||
} | } | ||||
static void | static void | ||||
tlb_invalidate_one(unsigned i) | tlb_invalidate_one(unsigned i) | ||||
{ | { | ||||
/* XXX an invalid ASID? */ | /* XXX an invalid ASID? */ | ||||
mips_wr_entryhi(TLBHI_ENTRY(MIPS_KSEG0_START + (2 * i * PAGE_SIZE), 0)); | mips_wr_entryhi(TLBHI_ENTRY(MIPS_KSEG0_START + (2 * i * PAGE_SIZE), 0)); | ||||
▲ Show 20 Lines • Show All 63 Lines • Show Last 20 Lines |
Necessary?