1 /*
2 * Copyright 2020-2021, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * X512 <danger_mail@list.ru>
7 */
8 #ifndef _RISCV64VMTRANSLATIONMAP_H_
9 #define _RISCV64VMTRANSLATIONMAP_H_
10
11
12 #include <atomic>
13
14 #include <vm/VMTranslationMap.h>
15 #include <arch_cpu_defs.h>
16 #include <kernel/smp.h>
17
18
19 enum {
20 PAGE_INVALIDATE_CACHE_SIZE = 64
21 };
22
23
24 struct RISCV64VMTranslationMap: public VMTranslationMap {
25 RISCV64VMTranslationMap(bool kernel,
26 phys_addr_t pageTable = 0);
27 virtual ~RISCV64VMTranslationMap();
28
29 virtual bool Lock();
30 virtual void Unlock();
31
32 virtual addr_t MappedSize() const;
33 virtual size_t MaxPagesNeededToMap(addr_t start,
34 addr_t end) const;
35
36 virtual status_t Map(addr_t virtualAddress,
37 phys_addr_t physicalAddress,
38 uint32 attributes, uint32 memoryType,
39 vm_page_reservation* reservation);
40 virtual status_t Unmap(addr_t start, addr_t end);
41
42 virtual status_t DebugMarkRangePresent(addr_t start, addr_t end,
43 bool markPresent);
44
45 virtual status_t UnmapPage(VMArea* area, addr_t address,
46 bool updatePageQueue);
47 virtual void UnmapPages(VMArea* area, addr_t base,
48 size_t size, bool updatePageQueue);
49 virtual void UnmapArea(VMArea* area,
50 bool deletingAddressSpace,
51 bool ignoreTopCachePageFlags);
52
53 virtual status_t Query(addr_t virtualAddress,
54 phys_addr_t* _physicalAddress,
55 uint32* _flags);
56 virtual status_t QueryInterrupt(addr_t virtualAddress,
57 phys_addr_t* _physicalAddress,
58 uint32* _flags);
59
60 virtual status_t Protect(addr_t base, addr_t top,
61 uint32 attributes, uint32 memoryType);
62 status_t ProtectPage(VMArea* area, addr_t address,
63 uint32 attributes);
64 status_t ProtectArea(VMArea* area,
65 uint32 attributes);
66
67 void SetFlags(addr_t virtualAddress,
68 uint32 flags);
69
70 virtual status_t ClearFlags(addr_t virtualAddress,
71 uint32 flags);
72
73 virtual bool ClearAccessedAndModified(
74 VMArea* area, addr_t address,
75 bool unmapIfUnaccessed,
76 bool& _modified);
77
78 virtual void Flush();
79
80 virtual void DebugPrintMappingInfo(addr_t virtualAddress);
81 virtual bool DebugGetReverseMappingInfo(
82 phys_addr_t physicalAddress,
83 ReverseMappingInfoCallback& callback);
84
85 inline phys_addr_t PageTable();
86 inline uint64 Satp();
87
88 status_t MemcpyToMap(addr_t to, const char *from,
89 size_t size);
90 status_t MemcpyFromMap(char *to, addr_t from,
91 size_t size);
92 status_t MemsetToMap(addr_t to, char c, size_t count);
93 ssize_t StrlcpyFromMap(char *to, addr_t from,
94 size_t size);
95 ssize_t StrlcpyToMap(addr_t to, const char *from,
96 size_t size);
97
98 inline CPUSet& ActiveOnCpus();
99 inline void InvalidatePage(addr_t address);
100
101 private:
102 std::atomic<Pte>* LookupPte(addr_t virtAdr, bool alloc,
103 vm_page_reservation* reservation);
104 phys_addr_t LookupAddr(addr_t virtAdr);
105
106 bool fIsKernel;
107 phys_addr_t fPageTable;
108 uint64 fPageTableSize; // in page units
109 CPUSet fActiveOnCpus;
110 int fInvalidPagesCount;
111 addr_t fInvalidPages[PAGE_INVALIDATE_CACHE_SIZE];
112 bool fInvalidCode;
113 };
114
115
116 inline phys_addr_t
PageTable()117 RISCV64VMTranslationMap::PageTable()
118 {
119 return fPageTable;
120 }
121
122
123 inline uint64
Satp()124 RISCV64VMTranslationMap::Satp()
125 {
126 SatpReg satp;
127 satp.ppn = fPageTable / B_PAGE_SIZE;
128 satp.asid = 0;
129 satp.mode = satpModeSv39;
130 return satp.val;
131 }
132
133
134 CPUSet&
ActiveOnCpus()135 RISCV64VMTranslationMap::ActiveOnCpus()
136 {
137 return fActiveOnCpus;
138 }
139
140
141 void
InvalidatePage(addr_t address)142 RISCV64VMTranslationMap::InvalidatePage(addr_t address)
143 {
144 if (fInvalidPagesCount < PAGE_INVALIDATE_CACHE_SIZE)
145 fInvalidPages[fInvalidPagesCount] = address;
146
147 fInvalidPagesCount++;
148 }
149
150
151 struct RISCV64VMPhysicalPageMapper: public VMPhysicalPageMapper {
152 RISCV64VMPhysicalPageMapper();
153 virtual ~RISCV64VMPhysicalPageMapper();
154
155 virtual status_t GetPage(phys_addr_t physicalAddress,
156 addr_t* _virtualAddress,
157 void** _handle);
158 virtual status_t PutPage(addr_t virtualAddress,
159 void* handle);
160
161 virtual status_t GetPageCurrentCPU(
162 phys_addr_t physicalAddress,
163 addr_t* _virtualAddress,
164 void** _handle);
165 virtual status_t PutPageCurrentCPU(addr_t virtualAddress,
166 void* _handle);
167
168 virtual status_t GetPageDebug(phys_addr_t physicalAddress,
169 addr_t* _virtualAddress,
170 void** _handle);
171 virtual status_t PutPageDebug(addr_t virtualAddress,
172 void* handle);
173
174 virtual status_t MemsetPhysical(phys_addr_t address, int value,
175 phys_size_t length);
176 virtual status_t MemcpyFromPhysical(void* to, phys_addr_t from,
177 size_t length, bool user);
178 virtual status_t MemcpyToPhysical(phys_addr_t to,
179 const void* from, size_t length,
180 bool user);
181 virtual void MemcpyPhysicalPage(phys_addr_t to,
182 phys_addr_t from);
183 };
184
185
186 #endif // _RISCV64VMTRANSLATIONMAP_H_
187