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