xref: /haiku/src/system/kernel/arch/riscv64/RISCV64VMTranslationMap.h (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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
117 RISCV64VMTranslationMap::PageTable()
118 {
119 	return fPageTable;
120 }
121 
122 
123 inline uint64
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&
135 RISCV64VMTranslationMap::ActiveOnCpus()
136 {
137 	return fActiveOnCpus;
138 }
139 
140 
141 void
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