summaryrefslogtreecommitdiff
path: root/libcpu/aarch64/common/include/tlb.h
blob: ede4c7fd83165910f624cb418f18b8b8279b5dca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-11-28     WangXiaoyao  the first version
 */
#ifndef __TLB_H__
#define __TLB_H__

#include <rtthread.h>
#include <stddef.h>
#include <stdint.h>
#include "mm_aspace.h"
#include "mmu.h"

#define TLBI_ARG(addr, asid)                                                   \
    ({                                                                         \
        rt_ubase_t arg = (rt_ubase_t)(addr) >> ARCH_PAGE_SHIFT;                \
        arg &= (1ull << 44) - 1;                                               \
        arg |= (rt_ubase_t)(asid) << MMU_ASID_SHIFT;                           \
        (void *)arg;                                                           \
    })

static inline void rt_hw_tlb_invalidate_all(void)
{
    __asm__ volatile(
        // ensure updates to pte completed
        "dsb ishst\n"
        "tlbi vmalle1is\n"
        "dsb ish\n"
        // after tlb in new context, refresh inst
        "isb\n" ::
            : "memory");
}

static inline void rt_hw_tlb_invalidate_all_local(void)
{
    __asm__ volatile(
        // ensure updates to pte completed
        "dsb nshst\n"
        "tlbi vmalle1is\n"
        "dsb nsh\n"
        // after tlb in new context, refresh inst
        "isb\n" ::
            : "memory");
}

static inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace)
{
#ifdef ARCH_USING_ASID
      if (aspace == &rt_kernel_space) {
          rt_hw_tlb_invalidate_all();
      } else {
          __asm__ volatile(
            // ensure updates to pte completed
            "dsb ishst\n"
            "tlbi aside1is, %0\n"
            "dsb ish\n"
            // after tlb in new context, refresh inst
            "isb\n" ::"r"(TLBI_ARG(0ul, aspace->asid))
                : "memory");
      }
#else
    rt_hw_tlb_invalidate_all();
#endif
}

static inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start)
{
    start = TLBI_ARG(start, 0);
    __asm__ volatile(
        "dsb ishst\n"
        "tlbi vaae1is, %0\n"
        "dsb ish\n"
        "isb\n" ::"r"(start)
        : "memory");
}

static inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start,
                                              size_t size, size_t stride)
{
    if (size <= ARCH_PAGE_SIZE)
    {
        rt_hw_tlb_invalidate_page(aspace, start);
    }
    else
    {
        rt_hw_tlb_invalidate_aspace(aspace);
    }
}

#endif /* __TLB_H__ */