1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2024-07-12 RT-Thread first version.
9 */
10 #define DBG_TAG "hw.asid"
11 #define DBG_LVL DBG_INFO
12 #include <rtdbg.h>
13
14 #include <rtthread.h>
15 #include <board.h>
16 #include <cache.h>
17 #include <mm_aspace.h>
18 #include <mm_page.h>
19 #include <mmu.h>
20 #include <riscv_mmu.h>
21 #include <tlb.h>
22
23 static rt_uint8_t ASID_BITS = 0;
24 static rt_uint32_t next_asid;
25 static rt_uint64_t global_asid_generation;
26 #define ASID_MASK ((1 << ASID_BITS) - 1)
27 #define ASID_FIRST_GENERATION (1 << ASID_BITS)
28 #define MAX_ASID ASID_FIRST_GENERATION
29
rt_hw_asid_init(void)30 void rt_hw_asid_init(void)
31 {
32 rt_uint64_t satp_reg = read_csr(satp);
33 satp_reg |= (((rt_uint64_t)0xffff) << PPN_BITS);
34 write_csr(satp, satp_reg);
35 __asm__ volatile("sfence.vma x0, x0");
36 unsigned short valid_asid_bit = ((read_csr(satp) >> PPN_BITS) & 0xffff);
37
38 // The maximal value of ASIDLEN, is 9 for Sv32 or 16 for Sv39, Sv48, and Sv57
39 for (unsigned i = 0; i < 16; i++)
40 {
41 if (!(valid_asid_bit & 0x1))
42 {
43 break;
44 }
45
46 valid_asid_bit >>= 1;
47 ASID_BITS++;
48 }
49
50 global_asid_generation = ASID_FIRST_GENERATION;
51 next_asid = 1;
52 }
53
_asid_acquire(rt_aspace_t aspace)54 static rt_uint64_t _asid_acquire(rt_aspace_t aspace)
55 {
56 if ((aspace->asid ^ global_asid_generation) >> ASID_BITS) // not same generation
57 {
58 if (next_asid != MAX_ASID)
59 {
60 aspace->asid = global_asid_generation | next_asid;
61 next_asid++;
62 }
63 else
64 {
65 // scroll to next generation
66 global_asid_generation += ASID_FIRST_GENERATION;
67 next_asid = 1;
68 rt_hw_tlb_invalidate_all_local();
69
70 aspace->asid = global_asid_generation | next_asid;
71 next_asid++;
72 }
73 }
74
75 return aspace->asid & ASID_MASK;
76 }
77
rt_hw_asid_switch_pgtbl(struct rt_aspace * aspace,rt_ubase_t pgtbl)78 void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl)
79 {
80 rt_uint64_t asid = _asid_acquire(aspace);
81 write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) |
82 (asid << PPN_BITS) |
83 ((rt_ubase_t)pgtbl >> PAGE_OFFSET_BIT));
84 asm volatile("sfence.vma x0,%0"::"r"(asid):"memory");
85 }
86
87