1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- /*
- * Copyright (c) 2006-2024, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-07-12 RT-Thread first version.
- */
- #define DBG_TAG "hw.asid"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include <rtthread.h>
- #include <board.h>
- #include <cache.h>
- #include <mm_aspace.h>
- #include <mm_page.h>
- #include <mmu.h>
- #include <riscv_mmu.h>
- #include <tlb.h>
- static rt_uint8_t ASID_BITS = 0;
- static rt_uint32_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
- void rt_hw_asid_init(void)
- {
- rt_uint64_t satp_reg = read_csr(satp);
- satp_reg |= (((rt_uint64_t)0xffff) << PPN_BITS);
- write_csr(satp, satp_reg);
- __asm__ volatile("sfence.vma x0, x0");
- 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_acquire(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_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl)
- {
- rt_uint64_t asid = _asid_acquire(aspace);
- write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) |
- (asid << PPN_BITS) |
- ((rt_ubase_t)pgtbl >> PAGE_OFFSET_BIT));
- asm volatile("sfence.vma x0,%0"::"r"(asid):"memory");
- }
|