diff --git a/components/mm/mm_aspace.h b/components/mm/mm_aspace.h index 900b3635bed1f45a4eee2401fa7ddb7fa0d42f96..a8cf6e8339cf93121686d7cfda5380928b47c7da 100644 --- a/components/mm/mm_aspace.h +++ b/components/mm/mm_aspace.h @@ -53,6 +53,8 @@ typedef struct rt_aspace struct _aspace_tree tree; struct rt_mutex bst_lock; + + rt_uint64_t asid; } *rt_aspace_t; typedef struct rt_varea diff --git a/libcpu/risc-v/t-head/c906/mmu.c b/libcpu/risc-v/t-head/c906/mmu.c index bdcfa7587da3fa426e2d6794d81aaee634614419..dc3ba0cfdd6a2395a6796ae55a4d7dda73498e63 100644 --- a/libcpu/risc-v/t-head/c906/mmu.c +++ b/libcpu/risc-v/t-head/c906/mmu.c @@ -41,14 +41,70 @@ static void *current_mmu_table = RT_NULL; volatile __attribute__((aligned(4 * 1024))) rt_ubase_t MMUTable[__SIZE(VPN2_BIT)]; +static rt_uint8_t ASID_BITS = 0; +static rt_uint16_t next_asid; +static rt_uint64_t global_asid_generation; +#define ASID_MASK ((1 << ASID_BITS) - 1) +#define ASID_FIRST_GENERATION (1 << ASID_BITS) +#define MAX_ASID ASID_FIRST_GENERATION + +static void _asid_init() +{ + unsigned int satp_reg = read_csr(satp); + satp_reg |= (((rt_uint64_t)0xffff) << PPN_BITS); + write_csr(satp, satp_reg); + unsigned short valid_asid_bit = ((read_csr(satp) >> PPN_BITS) & 0xffff); + + // The maximal value of ASIDLEN, is 9 for Sv32 or 16 for Sv39, Sv48, and Sv57 + for (unsigned i = 0; i < 16; i++) + { + if (!(valid_asid_bit & 0x1)) + { + break; + } + + valid_asid_bit >>= 1; + ASID_BITS++; + } + + global_asid_generation = ASID_FIRST_GENERATION; + next_asid = 1; +} + +static rt_uint64_t _asid_check_switch(rt_aspace_t aspace) +{ + if ((aspace->asid ^ global_asid_generation) >> ASID_BITS) // not same generation + { + if (next_asid != MAX_ASID) + { + aspace->asid = global_asid_generation | next_asid; + next_asid++; + } + else + { + // scroll to next generation + global_asid_generation += ASID_FIRST_GENERATION; + next_asid = 1; + rt_hw_tlb_invalidate_all_local(); + + aspace->asid = global_asid_generation | next_asid; + next_asid++; + } + } + + return aspace->asid & ASID_MASK; +} + void rt_hw_aspace_switch(rt_aspace_t aspace) { uintptr_t page_table = (uintptr_t)_rt_kmem_v2p(aspace->page_table); current_mmu_table = aspace->page_table; + rt_uint64_t asid = _asid_check_switch(aspace); write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) | + (asid << PPN_BITS) | ((rt_ubase_t)page_table >> PAGE_OFFSET_BIT)); - rt_hw_tlb_invalidate_all_local(); + asm volatile("sfence.vma x0,%0"::"r"(asid):"memory"); } void *rt_hw_mmu_tbl_get() @@ -482,6 +538,8 @@ void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr) mdesc++; } + _asid_init(); + rt_hw_aspace_switch(&rt_kernel_space); rt_page_cleanup(); } diff --git a/libcpu/risc-v/t-head/c906/riscv_mmu.h b/libcpu/risc-v/t-head/c906/riscv_mmu.h index 84b9097eaf5b3190a5fc2dceb5955b20fae65516..ddb3d0277d4672224a6f26246eb5afdee380143b 100644 --- a/libcpu/risc-v/t-head/c906/riscv_mmu.h +++ b/libcpu/risc-v/t-head/c906/riscv_mmu.h @@ -63,8 +63,8 @@ #define PAGE_ATTR_CB (PTE_BUF | PTE_CACHE) #define PAGE_ATTR_DEV (PTE_SO) -#define PAGE_DEFAULT_ATTR_LEAF (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_G | PTE_U | PAGE_ATTR_RWX | PTE_V) -#define PAGE_DEFAULT_ATTR_NEXT (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_G | PTE_V) +#define PAGE_DEFAULT_ATTR_LEAF (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_U | PAGE_ATTR_RWX | PTE_V) +#define PAGE_DEFAULT_ATTR_NEXT (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_V) #define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX) @@ -81,6 +81,8 @@ #define SATP_MODE_SV57 10 #define SATP_MODE_SV64 11 +#define PPN_BITS 44 + #define ARCH_VADDR_WIDTH 39 #define SATP_MODE SATP_MODE_SV39